コマンドの置き換えについて混乱しています。私はプログラミング言語マクロのようなコマンドの置き換えを考えています。サブシェルが最初に実行され、親コマンドが評価される前に$(...)
標準出力が置き換えられます。しかし、これはすべて真実ですか?
次のコマンドを実行しようとすると
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')"
これは期待どおりに出力されます。
答え2
Romeが言うことに加えて、コマンドは次のようになります。
echo {0..9}| xargs -n 2 | tac
これは生産します
8 9
6 7
4 5
2 3
0 1
意味のない$(echo 'echo')を使用するとエラーが発生します。
PS。長い答えの場合は、|
出力を1つのコマンドから次のコマンドにリダイレクトして、次のようにecho {0..9}
生成します。
0 1 2 3 4 5 6 7 8 9
xargs -n 2
この入力を受け入れて生成します。
0 1
2 3
4 5
6 7
8 9
最後に、対応するtac
入力を受け取り、反対の式を生成します。
8 9
6 7
4 5
2 3
0 1
これがもう少し明確になることを願っています。
編集する:
echo {0..9} | xargs -n 2 $(echo 'echo | tac')
+ echo 0 1 2 3 4 5 6 7 8 9
++ echo 'echo | tac'
+ xargs -n 2 echo '|' tac
| tac 0 1
| tac 2 3
| tac 4 5
| tac 6 7
| tac 8 9
これは初期構文を使用して bash に送信するコマンドです。何が起こっているのか明確で最後に送ります。xargs -n 2 echo '|' tac
答え3
重複する危険がありますが(他の人が明示的に言ったところはありません)、あなたの理由は次のとおりです。
echo {0..9} | xargs -n 2 $(echo 'echo | tac')
コマンドが実行することは、次のとおりです。
echo {0..9} | xargs -n 2 'echo' '|' 'tac'
比較する
echo {0..9} | xargs -n 2 echo foo bar
$(echo …)
これは、コマンドラインの全体構造()を解析した後に評価が実行されるため、出力ではコマンドに引数のみを追加できるためです。欲しいものを好きなようにするには、こう言う必要があります。echo (something) | xargs (args)
$(echo …)
xargs
エコ{0..9} |評価するxargs -n 2 $(echo 'echo | tac')
危険な場合がありますのでご注意くださいeval
。このコンテンツに関する警告をこのサイトで検索し、注意してください。