Kiedy używać () vs. {} w bash?

74

Studiuję skryptowanie powłoki za pomocą bash i muszę znać różnicę między (...)i {...}. Jak wybierać między nimi podczas pisania skryptu?

Gruby Umysł
źródło
1
Zobacz wiki.bash-hackers.org
Helio,
3
Miałeś na myśli wyłącznie w kontekście grupowania poleceń?
heemayl

Odpowiedzi:

87

Jeśli chcesz, aby skutki uboczne z listy poleceń wpływały na twoją bieżącą powłokę, użyj {...}
Jeśli chcesz odrzucić jakiekolwiek skutki uboczne, użyj(...)

Na przykład mogę użyć podpowłoki, jeśli:

  • chcę zmienić $IFSkilka poleceń, ale nie chcę zmieniać $IFSglobalnie dla bieżącej powłoki
  • cdgdzieś, ale nie chcę zmieniać $PWDbieżącej powłoki

Warto zauważyć, że w definicji funkcji można użyć nawiasów:

  • normalne użycie: nawiasy klamrowe: ciało funkcji wykonuje się w bieżącej powłoce; działania niepożądane pozostają po zakończeniu funkcji

    $ count_tmp() { cd /tmp; files=(*); echo "${#files[@]}"; }
    $ pwd; count_tmp; pwd
    /home/jackman
    11
    /tmp
    $ echo "${#files[@]}"
    11    
    
  • nietypowe użycie: nawiasy: ciało funkcji wykonuje się w podpowłoce; efekty uboczne znikają po wyjściu podpowłoki

    $ cd ; unset files
    $ count_tmp() (cd /tmp; files=(*); echo "${#files[@]}")
    $ pwd; count_tmp; pwd
    /home/jackman
    11
    /home/jackman
    $ echo "${#files[@]}"
    0
    

Dokumentacja

Glenn Jackman
źródło
11
Po wielu latach rozwoju powłoki nie wiedziałem, że możesz używać nawiasów do uruchamiania funkcji w podpowłokach. Co za świetny pomysł, aby uniknąć zanieczyszczenia globalnej przestrzeni nazw!
l0b0
7
Użycie localsłowa kluczowego ma długą drogę do usunięcia tego zanieczyszczenia.
glenn jackman
2
Tak, ale musisz pamiętać, aby zadeklarować każdą zmienną lokalnie, a to zakłóca kod.
l0b0
4
Wskazówka: jeśli chcesz funkcji bez skutków ubocznych, ale unikniesz nietypowej składni deklaracji funkcji (której edytory kodu mogą nie wiedzieć), po prostu użyj nawiasów w wywołaniu funkcji, a nie deklaracji:pwd; (count_tmp); pwd;
Juve
2
do powłoki ... foo () (:;) jest równoważne z foo () {(:;); } Tak to zgłasza, jeśli zapytasz!
Anthony
23

Z oficjalnej dokumentacji bash :

()

( list )

Umieszczenie listy poleceń między nawiasami powoduje utworzenie środowiska podpowłoki i wykonanie każdego z poleceń na liście w tej podpowłoce. Ponieważ lista jest wykonywana w podpowłoce, przypisania zmiennych nie pozostają aktywne po zakończeniu podpowłoki.

{}

{ list; }

Umieszczenie listy poleceń między nawiasami klamrowymi powoduje, że lista jest wykonywana w bieżącym kontekście powłoki. Nie jest tworzona podpowłoka. Wymagana jest następująca lista średników (lub znaków nowej linii).

Cyfrowa trauma
źródło
9

Kod w „{}” jest wykonywany w bieżącym wątku / procesie / środowisku, a zmiany są zachowywane, mówiąc bardziej zwięźle, kod jest uruchamiany w bieżącym zakresie.
Kod w „()” jest uruchamiany w osobnym, potomnym procesie bash, który jest odrzucany po wykonaniu. Ten proces potomny jest często nazywany podpowłoką i można go traktować jako nowy zakres potomny.

Jako przykład rozważ następujące ...

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

 ~ # 

Zauważ, że w pierwszym przykładzie z „{}” zmienna jest nadal ustawiana nawet po zamknięciu „}”, podczas gdy w przykładzie z „()” zmienna nie jest ustawiona poza zakresem „()”.

pali 2345
źródło
4

(...)są używane do uruchamiania kodu w podpowłoce. Użyty kod {...}poniżej nie będzie używany w podpowłoce.

Antoine Orsoni
źródło