コマンドの置き換えについて混乱しています。私はプログラミング言語マクロのようなコマンドの置き換えを考えています。サブシェルが最初に実行され、親コマンドが評価される前に$(...)
標準出力が置き換えられます。しかし、これはすべて真実ですか?
次のコマンドを実行しようとすると
echo {0..9} | xargs -n 2 $(echo 'echo | tac')
次の出力を見たいです。
8 9
6 7
4 5
2 3
0 1
しかし、代わりにこれを買う
| tac 0 1
| tac 2 3
| tac 4 5
| tac 6 7
| tac 8 9
それでは、| tac
コマンドラインの一部ではなく、echoの引数としてキャプチャされる原因は何ですか?正確なメカニズムと順序は何ですか?コマンドラインとコマンドの置き換えはどのように解析、スコープ、評価されますか? Linuxメタプログラムでコマンドラインを動的に構築できますか?
編集する
を使用できることを知っていますecho {0..9}| xargs -n 2 | tac
。質問は理論的です。サブシェルの例が同じ結果を生成しない理由に興味があります。
ベストアンサー1
見ている問題の根本的な原因は、コマンドラインのトークン化が発生する方法によるものです。この特別な場合、$(echo 'echo | tac')
拡張する前に、シェルはユーザーが1つのコマンド(echo {…}
)を実行し、|
その出力を別のコマンド(xargs -n 2 $(…)
)にパイプする意図を既に知っています。
その後、次のステップでは、パディングと中$(…)
括弧の拡張{…}
によって実際のコマンドが実行されます。この段階でパイプキャラクターを生産するなら、まあ、遅すぎてバスを逃したのは明らかです。
これで、特殊メタ文字として扱われなくなりますが、通常xargs
(=>メタ文字ではない)文字としてコマンドラインに含まれます。
再試行するには、次の手順を実行する必要がありますeval
。
eval "echo {0..9} | xargs -n 2 $(echo 'echo | tac')"
これは期待どおりに出力されます。