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
。どの単語にもワイルドカードがないため、ワイルドカードは何もしません。したがって、拡張コマンドは$a
2つの単語で構成されるため、コマンド(エイリアス、関数、組み込みコマンド、またはPATHの実行可能ファイル)は単一の引数で実行されます。my_cmd
--verbose
my_cmd
--verbose
2番目のフラグメントでも状況は似ておりURL=myurl
、拡張によってmy_cmd
3つの単語が生成されます--verbose
。これにより、URL=myurl
2つの引数を使用してコマンドを実行しようとします。
シェルコマンドURL=myurl my_cmd --verbose
は異なる方法で解析されます。最初の単語は変数への割り当てとして解析され、URL
その後にコマンド名があるため、割り当てはコマンド期間中にのみ環境変数を設定します。これは拡張後に実行される操作ではなく構文解析の一部であるため、等号はシェルソースコードの一部である必要があり、等号は一部の拡張の結果ではありません。
パラメータを含むコマンドを文字列に保存しないでください。。配列を使用してください。コマンドの実行に加えて変数を設定したりリダイレクトするコマンドなどの複雑なコマンドの場合は、可能であれば関数を使用し、そうでない場合は関数を使用してくださいeval
(正しい引用に特に注意してください)。