Bashスクリプトから生成されたコマンドの実行

Bashスクリプトから生成されたコマンドの実行

bashスクリプトでこのようなコマンドを作成しました。

a="my_cmd";
a="$a --verbose";
echo $a;
$a;

うまく動作し、私のコマンドを正しく実行します。ただし、ミックスに環境変数を追加すると競合が発生します。

a="my_cmd";
a="URL=myurl $a --verbose";
echo $a;
$a;

「該当するファイルやディレクトリはありません」で「URL=myurl」で中断されますが、eval() を使用して実行するとコマンドは正常に動作します。

a="my_cmd";
a="URL=myurl $a --verbose";
echo $a;
eval "$a";

2番目の例では、環境変数を混合に追加するとコマンドが中断されるのはなぜですか?

答え1

変数拡張を引用符なしでそのままにすると噴射そしてファイル名拡張子(つまり、ワイルドカード)。シェルコマンドでは解析されません。通常、実行されるシェルコードスニペットを動的に構成するときに実行する正しい方法は、シェルコードに解析する文字列をeval "$a"含めることです。a

最初のスニペットでは、値はa文字列ですmy_cmd --verbose。 2つmy_cmdの単語に分けて--verbose。どの単語にもワイルドカードがないため、ワイルドカードは何もしません。したがって、拡張コマンドは$a2つの単語で構成されるため、コマンド(エイリアス、関数、組み込みコマンド、またはPATHの実行可能ファイル)は単一の引数で実行されます。my_cmd--verbosemy_cmd--verbose

2番目のフラグメントでも状況は似ておりURL=myurl、拡張によってmy_cmd3つの単語が生成されます--verbose。これにより、URL=myurl2つの引数を使用してコマンドを実行しようとします。

シェルコマンドURL=myurl my_cmd --verboseは異なる方法で解析されます。最初の単語は変数への割り当てとして解析され、URLその後にコマンド名があるため、割り当てはコマンド期間中にのみ環境変数を設定します。これは拡張後に実行される操作ではなく構文解析の一部であるため、等号はシェルソースコードの一部である必要があり、等号は一部の拡張の結果ではありません。

パラメータを含むコマンドを文字列に保存しないでください。。配列を使用してください。コマンドの実行に加えて変数を設定したりリダイレクトするコマンドなどの複雑なコマンドの場合は、可能であれば関数を使用し、そうでない場合は関数を使用してくださいeval(正しい引用に特に注意してください)。

関連情報