これを実行すると:
echo "echo 'a'; echo 'b'"
これにより、実行できる文字列が生成され動作しますa\nb\n
。エコーが発生します。
しかし、これはうまくいきません。
$(echo "echo 'a'; echo 'b'")
なぜできないの?エコーだけでなく、どのコマンドでも機能しません。複数のコマンドを含む文字列を実行するには?
答え1
シェルでの$(echo "echo 'a'; echo 'b'")
コマンドの置き換えを参照してください。それはすべてです。したがって、これは拡張コマンドを置き換えるときの引数がSplit + Glob演算子の結果である単純なコマンドです。
シェルはコマンドの出力を取りますecho "echo 'a'; echo 'b'"
。この場合は、echo 'a'; echo 'b'\n
末尾の改行文字を削除して行き、echo 'a'; echo 'b'
変数の値に応じて分割します$IFS
。
$IFS
デフォルト値が変更されない場合は、echo
4'a';
ワードecho
になります'b'
。これらの各単語はワイルドカード文字の影響を受けます。これにはワイルドカード文字は含まれていないため、単語はそのまま残ります。
したがって、単純なコマンドを実行するための4つのパラメータがあります。最初の引数は、実行するコマンドを派生させるために使用されます。echo
ほとんどのシェルにはこれが組み込まれています。したがって、シェルはecho
この4つのパラメータを使用して組み込み関数を呼び出します。
echo
最初の(0番目)引数を無視し、空白文字で区切られ、改行文字で終わる別の引数を出力します。いくつかのecho
実装はバックスラッシュエスケープシーケンスを拡張しますが、ここではそうではありません。したがって、echo
出力は次のようになります。
'a'; echo 'b'\n
これを評価するには、つまり文字列をシェルコードとして解釈するには、次のようにしますeval
。
eval "echo 'a'; echo 'b'"
これも簡単なコマンドと見なされます。引用符のためeval
、シェルには2つの「単語」が表示されますecho 'a'; echo 'b'
。同様に、これは最初のコマンドから派生したコマンドの引数を形成します。
ここにあるコマンドはeval
シェルに組み込まれたコマンドです。もう一度eval
最初の引数を無視します。これが行うことは、別の引数(ここでは1つのみ)を空白で連結し、結果の文字列をシェルコードとして解釈することです。通訳するとき
echo 'a'; echo 'b'
シェルは、;
コマンドを区別するために引用されていないコマンドを表示します。最初は単純なコマンドで処理され、最終的にecho
2つの引数で呼び出されます...など。
答え2
if eval "( service networking restart &> /dev/null && ping -c3 google.com &> /dev/null )"; then
echo "service is running"
else
echo "service is not running"
fi