Chạy một chuỗi dưới dạng một lệnh trong tập lệnh Bash


152

Tôi có một đoạn script Bash xây dựng một chuỗi để chạy như một lệnh

Kịch bản:

#! /bin/bash

matchdir="/home/joao/robocup/runner_workdir/matches/testmatch/"

teamAComm="`pwd`/a.sh"
teamBComm="`pwd`/b.sh"
include="`pwd`/server_official.conf"
serverbin='/usr/local/bin/rcssserver'

cd $matchdir
illcommando="$serverbin include='$include' server::team_l_start = '${teamAComm}' server::team_r_start = '${teamBComm}' CSVSaver::save='true' CSVSaver::filename = 'out.csv'"

echo "running: $illcommando"
# $illcommando > server-output.log 2> server-error.log
$illcommando

mà dường như không cung cấp các đối số chính xác cho $serverbin.

Tập lệnh đầu ra:

running: /usr/local/bin/rcssserver include='/home/joao/robocup/runner_workdir/server_official.conf' server::team_l_start = '/home/joao/robocup/runner_workdir/a.sh' server::team_r_start = '/home/joao/robocup/runner_workdir/b.sh' CSVSaver::save='true' CSVSaver::filename = 'out.csv'
rcssserver-14.0.1

Copyright (C) 1995, 1996, 1997, 1998, 1999 Electrotechnical Laboratory.
2000 - 2009 RoboCup Soccer Simulator Maintenance Group.


Usage: /usr/local/bin/rcssserver [[-[-]]namespace::option=value]
                                 [[-[-]][namespace::]help]
                                 [[-[-]]include=file]
Options:
    help
        display generic help

    include=file
        parse the specified configuration file.  Configuration files
        have the same format as the command line options. The
        configuration file specified will be parsed before all
        subsequent options.

    server::help
        display detailed help for the "server" module

    player::help
        display detailed help for the "player" module

    CSVSaver::help
        display detailed help for the "CSVSaver" module

CSVSaver Options:
    CSVSaver::save=<on|off|true|false|1|0|>
        If save is on/true, then the saver will attempt to save the
        results to the database.  Otherwise it will do nothing.

        current value: false

    CSVSaver::filename='<STRING>'
        The file to save the results to.  If this file does not
        exist it will be created.  If the file does exist, the results
        will be appended to the end.

        current value: 'out.csv'

nếu tôi chỉ dán lệnh /usr/local/bin/rcssserver include='/home/joao/robocup/runner_workdir/server_official.conf' server::team_l_start = '/home/joao/robocup/runner_workdir/a.sh' server::team_r_start = '/home/joao/robocup/runner_workdir/b.sh' CSVSaver::save='true' CSVSaver::filename = 'out.csv'(trong đầu ra sau khi "runnning:") thì nó hoạt động tốt.



Lưu ý rằng trong một số trường hợp, bạn cần phải làm: echo | whateverCommandsthay vì chỉ whateverCommands(ví dụ: tôi phải làm như thế này | tail -`echo | whateverCommands`:)
Andrew

Câu trả lời:


279

Bạn có thể sử dụng evalđể thực thi một chuỗi:

eval $illcommando

2
Liệu eval có chuyển tiếp giá trị trả về lệnh ( giá trị trả về , không phải đầu ra chuỗi) không?
Tomáš Zato - Phục hồi Monica

3
evallà một lệnh xấu trong tất cả các ngôn ngữ lập trình vì vậy hãy thận trọng khi sử dụng nó.
PC của Krishnadas

1
eval "$illcommando", với dấu ngoặc kép , để lệnh của bạn không bị sai lệch trước khi chạy. Hãy thử evaling với một giá trị illcommando='printf "%s\n" " * "'có và không có dấu ngoặc kép để thấy sự khác biệt.
Charles Duffy

@ TomášZato-ReinstateMonica Có, nó chuyển tiếp giá trị trả về của lệnh. Tuy nhiên, nó KHÔNG đặt "${PIPESTATUS[@]}"biến trong bash đúng cách. Tuy nhiên, set -o pipefailkhông đúng cách evalđể trả về mã thoát thất bại nếu lệnh chứa lệnh không được chuyển thành lệnh thành công.
Cameron Hudson

Tôi đã cố gắng làm một cái gì đó như grep -E '$filter' unfiltered.txt > filtered.txt, tôi không biết tại sao nó hoạt động trên dòng lệnh và tại sao với các giá trị được tính toán, nó không hoạt động trong tập lệnh bash. Câu trả lời của bạn đã lưu tập lệnh của tôi. Tôi cũng sẽ thêm vào đây một số ví dụ tài liệu hay mà tôi đã sử dụng để hiểu rõ hơn về cách thức hoạt động của eval. linuxhint.com/bash_eval_command
student0495

28

Tôi thường đặt các lệnh trong ngoặc đơn $(commandStr), nếu điều đó không giúp tôi thấy chế độ gỡ lỗi bash tuyệt vời, hãy chạy tập lệnh nhưbash -x script


4
Tôi không chắc lệnhStSt đề cập đến điều gì, nhưng ít nhất điều này không hiệu quả với tôi. Sẽ tốt hơn nếu bạn sử dụng các ví dụ làm việc đầy đủ.
Robin Manoli

@RobinManoli Cải thiện sự rõ ràng cho ya.
Andrew

18
your_command_string="..."
output=$(eval "$your_command_string")
echo "$output"

10

đừng đặt lệnh của bạn trong các biến, chỉ cần chạy nó

matchdir="/home/joao/robocup/runner_workdir/matches/testmatch/"
PWD=$(pwd)
teamAComm="$PWD/a.sh"
teamBComm="$PWD/b.sh"
include="$PWD/server_official.conf"
serverbin='/usr/local/bin/rcssserver'    
cd $matchdir
$serverbin include=$include server::team_l_start = ${teamAComm} server::team_r_start=${teamBComm} CSVSaver::save='true' CSVSaver::filename = 'out.csv'

1
đã làm điều đó nhưng nơi tôi có các biến nên đi giống như một đối số tôi đã làm "${arg}". ví dụ: server :: team_l_start = "$ {teamAComm}"
João Portela

1

./me diễn viên grow_dead ()

Tôi đang tìm kiếm một cái gì đó như thế này, nhưng tôi cũng cần phải sử dụng lại cùng một chuỗi trừ hai tham số để kết thúc với một cái gì đó như:

my_exe ()
{
    mysql -sN -e "select $1 from heat.stack where heat.stack.name=\"$2\";"
}

Đây là một cái gì đó tôi sử dụng để theo dõi việc tạo stack stack openstack. Trong trường hợp này, tôi mong đợi hai điều kiện, một hành động 'TẠO' và trạng thái 'HOÀN THÀNH' trên một ngăn xếp có tên là "Somestack"

Để có được các biến đó tôi có thể làm một cái gì đó như:

ACTION=$(my_exe action Somestack)
STATUS=$(my_exe status Somestack)
if [[ "$ACTION" == "CREATE" ]] && [[ "$STATUS" == "COMPLETE" ]]
...

0

Đây là tập lệnh xây dựng lớp của tôi thực thi các chuỗi được lưu trữ trong heredocs :

current_directory=$( realpath "." )
GENERATED=${current_directory}/"GENERATED"
build_gradle=$( realpath build.gradle )

## touch because .gitignore ignores this folder:
touch $GENERATED

COPY_BUILD_FILE=$( cat <<COPY_BUILD_FILE_HEREDOC

    cp 
        $build_gradle 
        $GENERATED/build.gradle

COPY_BUILD_FILE_HEREDOC
)
$COPY_BUILD_FILE

GRADLE_COMMAND=$( cat <<GRADLE_COMMAND_HEREDOC

    gradle run

        --build-file       
            $GENERATED/build.gradle

        --gradle-user-home 
            $GENERATED  

        --no-daemon

GRADLE_COMMAND_HEREDOC
)
$GRADLE_COMMAND

Cô đơn ")" là loại xấu xí. Nhưng tôi không biết làm thế nào để khắc phục khía cạnh asthetic đó.


0

Để xem tất cả các lệnh đang được thực thi bởi tập lệnh, hãy thêm -xcờ vào dòng shabang của bạn và thực hiện lệnh bình thường:

#! /bin/bash -x

matchdir="/home/joao/robocup/runner_workdir/matches/testmatch/"

teamAComm="`pwd`/a.sh"
teamBComm="`pwd`/b.sh"
include="`pwd`/server_official.conf"
serverbin='/usr/local/bin/rcssserver'

cd $matchdir
$serverbin include="$include" server::team_l_start="${teamAComm}" server::team_r_start="${teamBComm}" CSVSaver::save='true' CSVSaver::filename='out.csv'

Sau đó, nếu đôi khi bạn muốn bỏ qua đầu ra gỡ lỗi, hãy chuyển hướng stderrở đâu đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.