tl; dr
ソールstuff
はおそらくあなたのために働くでしょう。
完全な答え
何が起こるのですか
を実行するとfoo $(stuff)
、次のようになります。
stuff
実行;
- その出力(stdout)は、印刷される代わり
$(stuff)
に、foo
; の呼び出しで置き換えられます。
- そして、
foo
そのコマンドライン引数は明らかに何かに依存して、実行されますstuff
返さ。
この$(…)
メカニズムは「コマンド置換」と呼ばれます。あなたの場合、メインコマンドはecho
基本的にコマンドライン引数を標準出力に出力します。そのstuff
ため、stdoutに出力しようとするものはすべて、キャプチャされ、に渡さecho
れ、stdoutに出力されecho
ます。
の出力stuff
を標準出力に出力したい場合は、soleを実行してくださいstuff
。
`…`
構文は同じ目的を果たし$(…)
、あなたが盲目的にそれらを交換することはできませんので、いくつかの違いが、けれどもあります(「コマンド置換」と同じ名前で)。参照してください。このFAQとこの質問を。
echo $(stuff)
何を避けてもいいですか?
echo $(stuff)
自分が何をしているのかを知っているなら、あなたが使いたいと思う理由があります。同じ理由で、自分echo $(stuff)
が何をしているのかわからない場合は避けるべきです。
ポイントはstuff
、echo $(stuff)
まったく同じではありません。後者はstuff
、デフォルト値の出力でsplit + glob演算子を呼び出すことを意味します$IFS
。コマンド置換を二重引用符で囲むと、これが防止されます。コマンド置換を単一引用符で囲むと、コマンド置換ではなくなります。
分割に関してこれを観察するには、次のコマンドを実行します。
echo "a b"
echo $(echo "a b")
echo "$(echo "a b")" # the shell is smart enough to identify the inner and outer quotes
echo '$(echo "a b")'
そしてグロビングのために:
echo "/*"
echo $(echo "/*")
echo "$(echo "/*")" # the shell is smart enough to identify the inner and outer quotes
echo '$(echo "/*")'
ご覧のとおり、echo "$(stuff)"
はに相当します(-ish *)stuff
。あなたはそれを使用することができますが、このように物事を複雑にすることのポイントは何ですか?
一方、あなたは、以下の場合にしたいの出力はstuff
、あなたがグロブ+分割を受けることを見つけるecho $(stuff)
便利。しかし、それはあなたの意識的な決定でなければなりません。
評価する必要のある出力(分割、グロビングなどを含む)を生成するコマンドがあり、シェルによって実行されるためeval "$(stuff)"
、可能性があります(この回答を参照)。出力を追加してから印刷する前に追加の分割+グロビングを行う必要があるコマンドを見たことはありません。故意に使用することecho $(stuff)
は非常に珍しいようです。
どうvar=$(stuff); echo "$var"
?
いい視点ね。このスニペット:
var=$(stuff)
echo "$var"
とecho "$(stuff)"
同等(-ish *)と同等でなければなりませんstuff
。コード全体の場合は、stuff
代わりに実行するだけです。
ただし、stuff
複数回の出力を使用する必要がある場合は、このアプローチ
var=$(stuff)
foo "$var"
bar "$var"
通常は
foo "$(stuff)"
bar "$(stuff)"
たとえそうfoo
でecho
ありecho "$var"
、コードを取得したとしても、このように保つ方が良いかもしれません。考慮事項:
var=$(stuff)
stuff
実行一度; コマンドが高速であっても、同じ出力を2回計算しないようにするのが正しいことです。またはstuff
、stdoutへの書き込み以外の効果(一時ファイルの作成、サービスの開始、仮想マシンの開始、リモートサーバーへの通知など)があるため、複数回実行する必要はありません。
stuff
時間依存または多少ランダムな出力が生成される場合、foo "$(stuff)"
およびから一貫性のない結果が得られる可能性がありbar "$(stuff)"
ます。var=$(stuff)
の値$var
が修正された後、同じコマンドライン引数を確実foo "$var"
にbar "$var"
取得できます。
場合によってfoo "$var"
はfoo $var
、特に複数の引数をstuff
生成する場合(必要な場合)を使用する必要がありfoo
ます(シェルがサポートしている場合は配列変数の方が適している場合があります)。繰り返しますが、あなたが何をしているかを知っています。それはになるとecho
の間の差echo $var
とecho "$var"
の間で同じであるecho $(stuff)
とecho "$(stuff)"
。
*同等(-ish)?
私は言ったecho "$(stuff)"
に等しい(-ish)stuff
。正確に同等ではない少なくとも2つの問題があります。
$(stuff)
stuff
サブシェルで実行されるため、echo "$(stuff)"
と同等(-ish)であると言う方が良い(stuff)
です。サブシェルの場合、実行するシェルに影響するコマンドはメインシェルに影響しません。
この例でstuff
はa=1; echo "$a"
:
a=0
echo "$(a=1; echo "$a")" # echo "$(stuff)"
echo "$a"
と比較する
a=0
a=1; echo "$a" # stuff
echo "$a"
そして
a=0
(a=1; echo "$a") # (stuff)
echo "$a"
別の例は、で始まるstuff
ことcd /; pwd
:
cd /bin
echo "$(cd /; pwd)" # echo "$(stuff)"
pwd
テストstuff
と(stuff)
バージョン。
echo
非制御データを表示するのに適したツールではありません。echo "$var"
私たちが話していたこれは、あるべきだったprintf '%s\n' "$var"
。しかし、質問が言及echo
しており、最も可能性の高いソリューションはそもそも使用echo
しないことなので、私はこれまで紹介printf
しないことにしました。
stuff
または(stuff)
、stdoutとstderrの出力をインターリーブしecho $(stuff)
、stuff
(最初に実行される)からすべてのstderr出力を出力し、次にecho
(最後に実行される)によって消化されたstdout出力のみを出力します。
$(…)
後続の改行を取り除き、それecho
を元に戻します。そのため、とecho "$(printf %s 'a')" | xxd
は異なる出力が得られますprintf %s 'a' | xxd
。
一部のコマンド(ls
たとえば)は、標準出力がコンソールかどうかによって動作が異なります。これls | cat
と同じではありませんls
ありません。同様echo $(ls)
にの動作も異なりls
ます。
置くls
一般的なケースには、さておき場合は、あなたがこの他の動作を強制する必要があり、その後stuff | cat
よりも優れているecho $(ls)
かecho "$(ls)"
、それは他のすべての問題は、ここで言及トリガされませんので。
終了ステータスが異なる可能性があります(このwikiの回答の完全性について言及されています。詳細については、評価に値する別の回答を参照してください)。