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


回答:


75

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

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

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

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

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


${...}回答に含めてもらえますか?
user1717828

3
@ user1717828何?どうして?変数拡張はリモートでこの質問と何の関係がありますか?シェルマニュアル全体を回答に含めるつもりはありません。
ジル 'SO-悪であるのをやめる'

1
変数拡張はリモートでこの質問と何の関係がありますか? 私は知りません、だから私は尋ねました:-)だから、中括弧の置換は括弧括弧の置換のようなものではないと推測しています。
user1717828

@ user1717828:変数の展開はサブシェルとは無関係です。それは完全に独立したメカニズムであり、始めたばかりの場合は間違いなく読む価値があります!
0xdd

1
@EnricoMariaDeAngelisこれは唯一の方法ではありませんが、最も自然な方法です。もう1つの方法はcommand | { read line; … }(シェルによって異なりlineますが、パイプラインの後でまだ利用できる場合とできない場合があります)。出力を生成するコマンドは入力を読み取るシェルとは独立して実行する必要があるため、すべての方法にサブシェルが含まれます。コマンドが純粋にシェルの内部にある場合(シェル構成と組み込みのみ、外部コマンドはない)、シェルはサブプロセスを作成しないかもしれませんが、それは単なる最適化であり、サブシェルを作成します。
ジル「SO-悪であるのをやめ

20

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

Bashは、commandサブシェル環境で実行することにより展開を実行します[...]



1
興味深いことに、CentOS 7では、bashマンページにはサブシェルが記載されていませんBash performs the expansion by executing command and replacing the command substitution with the standard output of the command, with any trailing newlines deleted.。これは意図的な省略であったのでしょうか。
-dr01

6
@ dr01それどころか、bash 4.4はその文の表現を「サブシェル」という単語を含むように変更しました。マニュアルでは、他のさまざまな構成体がサブシェルであると明示的に言及されていましたが、4.4まではコマンド置換について明示的に述べられていませんでした。
ジル「SO-停止されて悪」

はい、CentOS v7.4.1708(かなり最近)のbashはv4.2.46です。
dr01

5

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

あなたが持っているときの唯一の違い$( commands... )は、コードのこの部分が実行後に書いたcommands...すべてで置き換えられるcommands...ことstdoutです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.