※ bash の | (パイプライン) bash スクリプトを書いていて、自分の思うようにスクリプトが動かない。 どうしてか最初は、不思議に思ったけど、良く考えると、 なるほどと合点がいく。そんな話です。 変数 n に 1を代入してから、n+1 を n に代入、その n の値を表示 $ n=1;n=$((n+1));echo $n 2 もちろん、答えは 2 です。 では、パイプライン | を使うとどうなるか? $ n=1;n=$((n+1))|echo;echo $n 1 答えは 1 です。 @ n=$((n+1)) は何も出力せず、ehco は何も入力をしていないので、 @ パイプラインを使う必要性は、この場合はありません。実際に私が @ スクリプトを書こうとしたのは、パイプラインが必要な場合でしたが、 @ そのまま引用すると複雑になり過ぎるので、ここでは簡単な例にしています。 じゃあ、&& (論理積)なら $ n=1;n=$((n+1)) && echo;echo $n 2 @ A && B は A を実行して返値が 0以外なら B を実行します。 @ n=$((n+1)) は必ず 0以外を返しますので、B を実行します。 それでは、 ; では、 $ n=1;n=$((n+1)); echo;echo $n 2 もちろん 2 です。 @ A ; B は Aを実行してから、B を実行する。 @ 順番に実行する、ただそれだけです。 どうして、 | が 1を返すのか? 理由は、 A | B が、A と B を同時に実行するからです。 次の答えを考えると、よくわかります。 $ n=1;n=$((n+1))|n=$((n+2));echo $n n=$((n+1)) を実行すると、n=2 となって、n=$((n+2)) を実行すると、 それに 2 を足すから、n=4 .... そうじゃない。n=$((n+1)) と n=$((n+2)) は同時に実行される。 それじゃ、n=$((n+1)) の結果、n=1 となって、 n=$((n+2)) の結果 は n=2 となる。 で、パイプラインが終わった後は、どちらの値になるの? だから、パイプラインが始まる前のままなのね。 # man bash からの引用 > コマンド置換と非同期コマンドは、サブシェル環境内で呼び出さ > れます。このサブシェル環境はシェル環境を複製したものです。 > ただし、シェルが捕捉したトラップは、そのシェルの起動時に親 > から継承した値に再設定されます。パイプラインの一部として起 > 動された組み込みコマンドは、サブシェル環境で実行されます。 > サブシェル環境に対して行われた変更は、元のシェル実行環境に > 影響を及ぼすことはできません。 実際にやってみると、 $ n=1;echo `n=$((n+1))`;echo $n ##コマンド置換 $ n=1;n=$((n+1)) & echo ;echo $n ## 非同期コマンド も同様に答えが 1 になります。 # bash 2.04 を使用 # バージョンの古い bash では動作が違うようです