Я вивчаю сценарій оболонок з bash, і мені потрібно знати різницю між (...)
і {...}
. Як вибирається між цими двома під час написання сценарію?
Я вивчаю сценарій оболонок з bash, і мені потрібно знати різницю між (...)
і {...}
. Як вибирається між цими двома під час написання сценарію?
Відповіді:
Якщо ви хочете, щоб побічні ефекти списку команд впливали на вашу поточну оболонку, використовуйте {...}
Якщо ви хочете відкинути будь-які побічні ефекти, скористайтеся(...)
Наприклад, я можу використовувати підзаголовки, якщо:
$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
~ #
Зауважте, що в першому прикладі з "{}" змінна все ще встановлюється навіть після закриття "}", тоді як у прикладі з "()" змінна не встановлюється поза межами "()".
(...)
використовуються для запуску коду в підколонці. Код, що використовується у вікні {...}
, не буде використовуватися в підколонці .