パイプライン後に複数のコマンドとサブシェルを実行する

パイプライン後に複数のコマンドとサブシェルを実行する

まあ、私はBashで(デフォルトでは「lastpipe」bashオプションが有効になっていない場合)、パイプの後に割り当てられたすべての変数が実際にサブシェルで実行され、変数自体がサブシェルが実行された後に消えることを知っています。親プロセスでは使用できなくなります。しかし、いくつかのテストをしてみると、次のような動作が見つかりました。

A)2番目のコマンド(a = 2)は値を割り当て、次を返します。

[root@centos01]# a=1; a=2; a=10 | echo $a
2

B)3番目のコマンド(a = 10)は値を割り当て、次を返します。

[root@centos01]# a=1; a=2; a=10; a=20 | echo $a
10

C)4番目のコマンド(a = 20)は、以下を割り当てて返します。

[root@centos01]# a=1; a=2; a=10; a=20; touch fileA.txt | echo $a
20

だから:

  • コマンドシーケンスの最後の変数割り当てが実際に実行されないのはなぜですか? (それではなぜサブシェルに捕捉され、echoコマンドによって返されないのですか?)

  • テストCでは、「touch」コマンドは実際にディレクトリに「fileA.txt」ファイルを生成します。それでは、ステップAとステップBで行われた変数割り当て順序の最後のコマンドが機能しないのはなぜですか?これについての技術的な説明を知っている人はいますか?

ベストアンサー1

まず、いくつかの名前に同意するためにシェルが入力を解釈する方法は次のとおりです。

$ a=1; a=2; a=10 | echo $a
  ^^^  ^^^  ^^^^^^^^^^^^^^
    \    \         \_ Pipeline
     \    \_ Simple command
      \_ Simple command

パイプラインは2つの簡単なコマンドで構成されています。

$ a=10 | echo $a
  ^^^^   ^^^^^^^
     \       \_ Simple command
      \_ Simple command

(Bashマニュアルには明示的に言及されていないかもしれませんが、POSIXシェル構文変数の割り当てだけで簡単なコマンドを設定できます。

a=1;a=2;パイプラインの一部ではありません。 A は;パイプの一部として存在しない限りパイプを終了します。複合コマンド。たとえば、

{ a=1; a=2; a=10; } | echo $a

あなたの例では、以下を実行してくださいa=10echo $a2つの異なる、独立サブシェル環境1は、すべて基本環境のコピーとして作成されます。サブシェルは親実行環境を変更しないでください2。関連コンテンツの引用POSIX部分:

サブシェル環境は、シェル環境のコピーとして作成する必要があります。 [...]サブシェル環境への変更は、シェル環境に影響を与えてはいけません。

そして

さらに、マルチコマンドパイプラインの各コマンドはサブシェル環境にありますが、拡張機能によってパイプラインの一部またはすべてのコマンドを現在の環境で実行できます。他のすべてのコマンドは、現在のシェル環境内で実行する必要があります。

したがって、例のすべてのコマンドが実際に実行されている間、パイプラインの左側の部分の割り当ては目立つ効果はありません。aそのサブシェル環境のコピーのみが変更され、そのコピーはサブシェルが終了すると失われます。

パイプの両端にあるサブシェルが互いに直接対話できる唯一の方法は、パイプ自体を介することです。左側の標準出力は右側の標準入力に接続されます。a=10パイプを介して何も送信されないため、に影響を与える可能性はありませんecho $a


1 このオプションが設定されている場合(デフォルトではオフ、組み込みコマンドを使用して有効)、Bashは現在のシェルのパイプラインで最後のコマンドを実行できます。バラよりlastpipeshopt管路Bashのマニュアルにあります。しかし、これはあなたの質問とは関係ありません。

2 実際/歴史的観点からU&Lの詳細を見ることができます。この回答到着POSIXシェルスクリプトパイプラインで実行された最後の関数が変数値を保持しないのはなぜですか?

おすすめ記事