Когда использовать () vs. {} в bash?

57

Я изучаю shell-скрипты с bash, и мне нужно знать разницу между (...) и {...} . Как выбрать между ними при написании сценария?

    
задан Fat Mind 07.04.2015 в 16:22
источник

4 ответа

74

Если вы хотите, чтобы побочные эффекты списка команд влияли на вашу текущую оболочку, используйте {...}
Если вы хотите отказаться от каких-либо побочных эффектов, используйте (...)

Например, я мог бы использовать подоболочку, если I:

  • хотите изменить $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
    

Документация

    
ответ дан glenn jackman 07.04.2015 в 16:40
источник
20

Из официальной документации по bash :

  

()      

( list )
         

Размещение списка команд между скобками приводит к созданию среды подклассов, и каждая из команд в списке должна выполняться в этой подоболочке. Поскольку список выполняется в подоболочке, присваивания переменных не остаются в силе после завершения подоболочки.

  
     

{}      

{ list; }
         

Размещение списка команд между фигурными скобками приводит к тому, что список будет выполнен в текущем контексте оболочки. Не создается подоболочка. Требуется список с запятой (или новой строкой).

  
    
ответ дан Digital Trauma 07.04.2015 в 21:45
9

Код в '{}' выполняется в текущем потоке / процессе / среде, и изменения сохраняются, чтобы сделать его более кратким, код запускается в текущей области.
Код в '()' запускается внутри отдельного дочернего процесса bash, который отбрасывается после выполнения. Этот детский процесс часто называют sub-shell и может рассматриваться как новый, подобный ребенку объем.

В качестве примера рассмотрим следующее ...

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

 ~ # 

Обратите внимание, что в первом примере с '{}' переменная по-прежнему установлена ​​даже после закрытия '}', тогда как в примере с '() переменная не задана за пределами области' () '.     

ответ дан smokes2345 07.04.2015 в 18:53
4

(...) используются для запуска кода в под-оболочке. Использованный код bewteen {...} не будет использоваться в под-оболочке.

    
ответ дан Antoine Orsoni 07.04.2015 в 16:27