bashで()と{}を使用する場合


74

私はbashでシェルスクリプトを勉強していますが、との違いを知る必要が(...)あり{...}ます。スクリプトを作成するときに、2つをどのように選択しますか?



3
コマンドのグループ化のコンテキストでのみ意味しますか?
heemayl

回答:


87

コマンドリストの副作用が現在のシェルに影響するようにする{...}
場合は、を使用します。副作用を破棄する場合は、(...)

たとえば、次の場合はサブシェルを使用します。

  • 変更したい$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

ドキュメンテーション


11
長年のシェル開発の後、括弧を使用してサブシェルで関数を実行できるとは知りませんでした。グローバル名前空間の汚染を避けるためのなんて素晴らしいアイデアでしょう!
-l0b0

7
localキーワードを使用すると、その汚染をきれいにするのに大いに役立ちます。
グレンジャックマン

2
ええ、しかし、すべての変数をローカルに宣言することを覚えておく必要があり、コードが乱雑になります。
l0b0

4
ヒント:あなたは副作用のない機能をしたいが、(コードエディタが認識できない場合があります)、異常な関数宣言の構文を避けるなら、ちょうどむしろ宣言よりも、関数呼び出しに括弧を使用しますpwd; (count_tmp); pwd;
ユーベ

2
シェルへ... foo()(:;)はfoo()と同等です{(:;); }それはあなたが尋ねた場合、それがそれを報告する方法です!
アンソニー

23

公式のbashドキュメントから

()

( list )

括弧の間にコマンドのリストを配置すると、サブシェル環境が作成され、リスト内の各コマンドがそのサブシェルで実行されます。リストはサブシェルで実行されるため、変数の割り当てはサブシェルの完了後も有効になりません。

{}

{ list; }

中括弧の間にコマンドのリストを配置すると、現在のシェルコンテキストでリストが実行されます。サブシェルは作成されません。リストに続くセミコロン(または改行)が必要です。


9

'{}'のコードは現在のスレッド/プロセス/環境で実行され、変更は保持されます。より簡潔に言えば、コードは現在のスコープで実行されます。
「()」のコードは、実行後に破棄されるbashの別の子プロセス内で実行されます。この子プロセスはしばしばサブシェルと呼ばれ、新しい子のようなスコープと考えることができます。

例として、次のことを考慮してください...

 ~ # { test_var=test }
 ~ # echo $test_var
 test
 ~ # ( test_var2=test2 )
 ~ # echo $test_var2

 ~ # 

「{}」の最初の例では、変数は「}」を閉じた後でも設定されていますが、「()」の例では、変数は「()」の範囲外に設定されていません。


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