web-dev-qa-db-ja.com

値を含む文字列をbashのコマンドとして実行するにはどうすればよいですか?

これが私の小さなbashスクリプトスニペットです。

i=5
command='echo $i'
$command

このスクリプトで5を出力して、エコーを実行して5を出力してほしいのですが、代わりに$iを出力し続けます。これを解決するにはどうすればよいですか?

6
posixKing

それは:

eval "$command"

$commandの内容をシェルコードとして評価する場合。

$command-で始まらないことが保証できない場合(evalのような一部のシェルではbashがオプションとして扱われる可能性があります)、あなたは実行したいかもしれません:

eval " $command"

代わりに。この余分な先行スペースは、コマンドの解析方法に影響を与えず、$commandで始まる場合、-evalのオプションとして扱われるのを防ぎます。 eval -- "$command"は一部のシェル(bashを含む)でも機能しますが、POSIX(IIRC)では機能せず、dashやBourne Shellなどでは機能しません。

$commandはおそらく次のようになります:

command='echo "$i"'

$iがsplit + globの対象になることを意図していない限り

コードを「変数」に格納するための潜在的に優れた方法は、関数を使用することです。

mycommand() { echo "$i"; }

mycommandはすでに既存のコマンドであるため、commandの代わりにcommandを使用します)。

$commandbreak/continue/returnの場合、動作はシェルによって異なります。

$command簡単なコマンドを保存したい場合は、Wordのリストで、最初にWordのリストを引数として実行するコマンドとして検索されます。配列変数を使用します。

command=('echo' '$i' "$i")
"${command[@]}"

これは、echoを実行し、echo$iおよび$iの内容を引数として使用します。

command='echo $i ;x /* '$i
$command

(デフォルト値は$IFSです)は、ほとんど意味がありません。そこで、$commandには文字列が含まれます。最初の$iはそのままで、2番目は展開され(単一引用符の外側)、次にその文字列はsplit + globの対象になります($commandは二重引用符の内側ではないため)。 単純なコマンドとして再び扱われる単語の数になります。

13