在Bash脚本中将字符串作为命令运行


152

我有一个Bash脚本,该脚本生成一个字符串以作为命令运行

脚本:

#! /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

这似乎无法将参数正确地提供给$serverbin

脚本输出:

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'

如果我只是粘贴命令/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'(在“ runnning:”之后的输出中),它就可以正常工作。



请注意,在某些情况下,您需要执行:echo | whateverCommands而不是仅仅whateverCommands(例如,我必须这样做| tail -`echo | whateverCommands`
安德鲁(Andrew

Answers:


278

您可以eval用来执行一个字符串:

eval $illcommando

2
eval是否将命令返回值(返回值,而不是字符串输出)传递给其他人?
托马什Zato -恢复莫妮卡

3
eval在所有编程语言中都是邪恶的命令,因此请谨慎使用。
Krishnadas PC

1
eval "$illcommando"用引号引起来,以便在运行命令之前不要对其进行任何处理。尝试eval使用illcommando='printf "%s\n" " * "'带引号和不带引号的值来查看区别。
查尔斯·达菲

@TomášZato-ReinstateMonica是的,它确实转发了命令的返回值。但是,它不能"${PIPESTATUS[@]}"在bash中正确设置变量。但是,如果命令包含传递给成功命令的失败命令,set -o pipefail则确实会导致eval返回失败退出代码。
卡梅隆·哈德森

我试图做类似的事情grep -E '$filter' unfiltered.txt > filtered.txt,我不知道为什么它可以在命令行中使用,为什么用计算值在bash脚本中不起作用。您的答案保存了我的脚本。我还将在此处添加一些很好的文档示例,以更好地了解eval的工作原理。linuxhint.com/bash_eval_command
student0495

28

我通常将命令放在括号内$(commandStr),如果这对我发现bash调试模式没有帮助,请以bash -x script


4
我不确定commandStr指的是什么,但是至少这对我不起作用。最好使用完整的示例示例。
罗宾·马诺利

@RobinManoli改进了ya的清晰度。
安德鲁(Andrew)

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

10

不要将命令放在变量中,只需运行它

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
就是那样。但是我的变量应该和我做的一个参数一样"${arg}"。例如:服务器:: team_l_start = “$ {} teamAComm”
若昂·波特拉

1

./me强制调用raise_dead()

我一直在寻找类似的东西,但是我还需要重用相同的字符串减去两个参数,所以最终得到了类似的东西:

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

这是我用来监视Openstack Heat Stack创建的东西。在这种情况下,我期望两个条件,即名为“ Somestack”的堆栈上的操作“ CREATE”和状态“ COMPLETE”

要获取这些变量,我可以执行以下操作:

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

0

这里是我的gradle这个构建脚本存储在执行字符串here文档

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

孤独的“)”有点丑陋。但是我不知道如何解决这一美学问题。


0

要查看脚本正在执行的所有命令,请将-x标志添加到您的shabang行中,然后正常执行该命令:

#! /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'

然后,如果您有时想忽略调试输出,请重定向stderr到某个地方。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.