Bashのパイプ(|)と論理AND(&&)優先順位

Bashのパイプ(|)と論理AND(&&)優先順位

演算子優先順位を持つクラシックシナリオには、次の行があります。

(cd ~/screenshots/ && ls screenshot* | head -n 5)

そしてそれが解析されたか((A && B) | C)どうか(A && B | C)...

これほぼ公式文書確立されたここパイプがリストに表示されないため、単にテーブルにチェックインすることはできません。

さらに、bashでは(作業の順序を変更できるだけでなく、次のようなこともできます。サブシェルの作成したがって、この行が前の行と同じであると100%確信することはできません。

((cd ~/screenshots/ && ls screenshot*) | head -n 5)

より一般的に知る方法アスパラギン酸アミノ転移酵素バッシュわかりましたか? Pythonには、タスクの順序を簡単に再確認できるようにツリーを提供する関数があります。

答え1

cd ~/screenshots/ && ls screenshot* | head -n 5

これは次のとおりです。

cd ~/screenshots && { ls screenshot* | head -n 5 ; }

(これ中かっこはコマンドを一緒にグループ化するため、サブシェルは必要ありません。)。したがって、優先順位は.(より堅固にバインドされている)の優先順位|よりも高くなります。それは、&&||

A && B | C

そして

A || B | C

常に意味BからCへの出力のみを提供。必要に応じて、コマンドを単一のエンティティとして一緒に使用するか、リンクして明確にすること(...)ができます。{ ... ; }

{ A && B ; } | C
A && { B | C ; } # This is the default, but you might sometimes want to be explicit

いくつかの異なるコマンドを使用してこれをテストできます。走れば

echo hello && echo world | tr a-z A-Z

それからあなたは得るでしょう

hello
WORLD

後ろに:tr a-z A-Z大文字で入力してくださいecho world、パイピングだけで自分で通過するのが見られますecho hello


これはいで定義シェル構文、あまり明確ではありませんが、and_or生産(&&/用)は本文にaaが含まれているだけで定義され||ています。pipelinepipelinecommandいいえ組み込みand_or-complete_command本番のみに到達できand_or、最上位レベルと関数やループなどの構造構成内にのみ存在します。

この構文を手動で適用してコマンドの構文解析ツリーを取得できますが、Bash自体は何も提供しません。私は自分で構文解析する以上の機能を実行するシェルを知りません。

シェル構文には、正式にのみ定義される特殊なケースが多数あり、正しく定義することは困難な作業になる可能性があります。 Bash自体も時には間違っています。したがって、実際の状況と理想的な状況は異なる場合があります。

文法を一致させ、ツリーを生成する外部パーサーがあります。私はこれらの外部パーサーを広くお勧めします。モビック、最も信頼できる人になろうとします。

答え2

長い話を短く;:、、などの区切り文字を一覧表示し、解析順序を決定します&&&||

これバッシュマニュアル私たちに教えてください:

AND および OR リストは 1 つ以上のシーケンスです。管路制御演算子を&&と||で区切ります。

それともバッシュハッカーのwiki一般的な話す

<PIPELINE1> && <PIPELINE2>

cd ~/screenshots/ && ls screenshot* | head -n 5 パイプls screenshot* | head -n 5と簡単なコマンドがありますcd ~/screenshots/。指示に注意してください

パイプラインの各コマンドは、別々のプロセス(つまりサブシェルで)で実行されます。

一方(cd ~/screenshots/ && ls screenshot*) | head -n 5、違います。パイプラインがあります。左側にはサブシェルがあり、右側にはサブシェルがありますhead -n 5。この場合、OP表記法を使用すると、次のようになります。(A && B) | C


別の例を挙げましょう。

$ echo foo | false &&  echo 123 | tr 2 5
$

ここにリストがあります<pipeline1> && <pipeline2>。パイプラインの終了状態が最後のコマンドと同じで、false負の状態(つまり失敗)を返すことがわかっているため、&&右側は実行されません。

$ echo foo | true &&  echo 123 | tr 2 5
153

ここで、左パイプは正常終了状態なので、右パイプが実行され、出力が表示されます。


シェル構文は実際の実行順序を意味しません。そのうちの1つを引用してください。ザイルズの答え:

パイプラインコマンドが同時に実行されます。 ps | grep ...を実行するときにpsまたはgrepが最初に開始されるかどうかは運の問題です(またはシェル操作の詳細とカーネル内部スケジューラの微調整の問題)。とにかく彼らは続く。

Bashのマニュアルから:

AND リストと OR リストは左の関連付けで実行されます。

これに基づいて、前のcd ~/screenshots/ && ls screenshot* | head -n 5コマンドが成功すると最初cd ~/screenshots/に実行されますが、パイプラインにあるためではなく、おそらく最初のプロセスが作成された可能性があります。ls screenshot* | head -n 5head -n 5ls

答え3

これは次に指定された場所ですbash(1)

SHELL GRAMMAR
[...]
   Pipelines
       A  pipeline  is  a sequence of one or more commands separated by one of
       the control operators | or |&.
[...]
   Lists
       A list is a sequence of one or more pipelines separated by one  of  the
       operators ;, &, &&, or ||, and optionally terminated by one of ;, &, or
       <newline>.

したがって、&&配管を外してください。

答え4

あなたは試すことができますecho hello && echo world | less。優先順位が高いことがわかります|(コマンドパイプラインはコマンドです)。 2番目の例はいいえ同じ。しかし、cd出力がないので微妙な違いはありません。

関連情報