web-dev-qa-db-ja.com

$()はサブシェルですか?

サブシェル構文が_(<commands...>)_であることを理解しています。$()は、変数値を取得できるサブシェルにすぎませんか?

注:これは、ドキュメントの異なる表現に基づくbash 4.4に適用されます。

55
leeand00

$(…)は、定義によりサブシェルです。これはシェルのランタイム状態のコピーです。サブシェルで行われた状態の変更は、親には影響しません。サブシェルは通常 forking 新しいプロセスによって実装されます(ただし、一部のシェルはこれを最適化する場合があります)。

変数値を取得できるのはサブシェルではありません。変数の変更が親に影響を与えた場合、それはサブシェルにはなりません。これは、親が取得できるoutputサブシェルです。 $(…)によって作成されたサブシェルの標準出力はパイプに設定されており、親はそのパイプから読み取り、出力を収集します。

サブシェルを作成する構成は他にもいくつかあります。私はこれがbashの完全なリストだと思います:

  • grouping のサブシェル:_( … )_はサブシェルを作成するだけで、サブシェルが終了するのを待ちます)。コマンドを純粋に構文上の目的でグループ化し、サブシェルを作成しない_{ … }_と対照的です。
  • Background :_… &_はサブシェルを作成し、終了するのを待ちません。
  • パイプライン :_… | …_は、2つのサブシェル(左側と右側に1つずつ)を作成し、両方が終了するのを待ちます。シェルはパイプを作成し、左側の標準出力をパイプの書き込み側に接続し、右側の標準入力を読み取り側に接続します。一部のシェル(ksh88、ksh93、zsh、bash lastpipeオプション 設定して有効)では、右側が元のシェルで実行されるため、パイプライン構造は1つしか作成しませんサブシェル。
  • コマンド置換$(…)(_`…`_とも表記)は、標準出力がパイプに設定されたサブシェルを作成し、親で出力を収集して、その出力に展開します。末尾の改行を差し引いたもの。 (そして、出力はさらに分割とグロブの対象になるかもしれませんが、それは別の話です。)
  • プロセス置換<(…)は、標準出力がパイプに設定されたサブシェルを作成し、パイプの名前に展開します。親(または他のプロセス)がパイプを開いてサブシェルと通信する場合があります。 >(…)も同じですが、標準入力のパイプを使用します。
  • Coprocess :_coproc …_はサブシェルを作成し、終了するのを待ちません。サブシェルの標準入力と出力はそれぞれパイプに設定され、親は各パイプのもう一方の端に接続されています。

¹ 別のシェルを実行するのとは対照的に

Bashバージョン4.4のbash(1)のマニュアルページの「EXPANSION」セクション、「Command Substitution」サブセクションから:

Bashは、サブシェル環境でcommandを実行して拡張を実行します[...]

はい、_( commands... )_は別のプロセスで_commands..._を実行するbashサブシェルです。

$( commands... )を使用する場合の唯一の違いは、コードのこの部分が_commands..._の実行後に__commands..._がstdoutに書き込んだすべてのものに置き換えられることです。

5
Iskustvo