回答:
コマンドリストの副作用が現在のシェルに影響するようにする{...}
場合は、を使用します。副作用を破棄する場合は、(...)
たとえば、次の場合はサブシェルを使用します。
$IFS
いくつかのコマンドのために、私は変更したくない$IFS
現在のシェルに対してグローバルcd
どこかに、しかし、私は$PWD
現在のシェルのを変更したくない関数定義では括弧を使用できることに注意してください。
通常の使用法:中括弧:関数本体は現在のシェルで実行されます。関数が完了した後も副作用が残る
$ count_tmp() { cd /tmp; files=(*); echo "${#files[@]}"; }
$ pwd; count_tmp; pwd
/home/jackman
11
/tmp
$ echo "${#files[@]}"
11
異常な使用法:括弧:関数本体はサブシェルで実行されます。サブシェルが終了すると副作用が消えます
$ cd ; unset files
$ count_tmp() (cd /tmp; files=(*); echo "${#files[@]}")
$ pwd; count_tmp; pwd
/home/jackman
11
/home/jackman
$ echo "${#files[@]}"
0
local
キーワードを使用すると、その汚染をきれいにするのに大いに役立ちます。
pwd; (count_tmp); pwd;
公式のbashドキュメントから:
()
( list )
括弧の間にコマンドのリストを配置すると、サブシェル環境が作成され、リスト内の各コマンドがそのサブシェルで実行されます。リストはサブシェルで実行されるため、変数の割り当てはサブシェルの完了後も有効になりません。
{}
{ list; }
中括弧の間にコマンドのリストを配置すると、現在のシェルコンテキストでリストが実行されます。サブシェルは作成されません。リストに続くセミコロン(または改行)が必要です。
'{}'のコードは現在のスレッド/プロセス/環境で実行され、変更は保持されます。より簡潔に言えば、コードは現在のスコープで実行されます。
「()」のコードは、実行後に破棄されるbashの別の子プロセス内で実行されます。この子プロセスはしばしばサブシェルと呼ばれ、新しい子のようなスコープと考えることができます。
例として、次のことを考慮してください...
~ # { test_var=test }
~ # echo $test_var
test
~ # ( test_var2=test2 )
~ # echo $test_var2
~ #
「{}」の最初の例では、変数は「}」を閉じた後でも設定されていますが、「()」の例では、変数は「()」の範囲外に設定されていません。
(...)
サブシェルでコードを実行するために使用されます。以下で使用されるコードは、サブシェルで{...}
は使用されません。