Коли використовувати () vs. {} у bash?


74

Я вивчаю сценарій оболонок з bash, і мені потрібно знати різницю між (...)і {...}. Як вибирається між цими двома під час написання сценарію?


1
Дивіться wiki.bash-hackers.org
Геліо

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ключового слова проходить довгий шлях до очищення цього забруднення.
glenn jackman

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

 ~ # 

Зауважте, що в першому прикладі з "{}" змінна все ще встановлюється навіть після закриття "}", тоді як у прикладі з "()" змінна не встановлюється поза межами "()".


4

(...)використовуються для запуску коду в підколонці. Код, що використовується у вікні {...}, не буде використовуватися в підколонці .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.