文字列を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

回答:


279

を使用evalして文字列を実行できます。

eval $illcommando

2
DOESは、コマンドの戻り値(往路EVAL 戻り値ではなく、文字列出力)?
トマーシュZato -復活モニカ

3
evalすべてのプログラミング言語で邪悪なコマンドなので、注意して使用してください。
Krishnadas PC、2018

1
eval "$illcommando"引用符で、あなたのコマンドは、それの実行前にマングル持っていないように。eval値をillcommando='printf "%s\n" " * "'引用符付きまたは引用符なしで試して、違いを確認してください。
Charles Duffy

@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が何を指しているのかはわかりませんが、少なくとも私にとってはうまくいきませんでした。完全に機能する例を使用することをお勧めします。
Robin Manoli 2013年

@RobinManoli yaの明快さを改善しました。
Andrew


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()をキャストします

私はこのようなものを探していましたが、同じ文字列から2つのパラメーターを引いたものも再利用する必要があったため、次のようなものになりました。

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

これは、OpenStackヒートスタックの作成を監視するために使用するものです。この場合、「Somestack」という名前のスタックでのアクション「CREATE」とステータス「COMPLETE」の2つの条件が予想されます。

これらの変数を取得するには、次のようにします。

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

0

これが、ヒアドキュメントに格納されている文字列を実行する私のgradleビルドスクリプトです:

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どこかにリダイレクトします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.