Wann benutzt man () vs. {} in der Bash?


Antworten:


87

Wenn sich die Nebenwirkungen der Befehlsliste auf Ihre aktuelle Shell auswirken sollen , verwenden {...}
Sie Wenn Sie alle Nebenwirkungen verwerfen möchten, verwenden Sie(...)

Zum Beispiel könnte ich eine Subshell verwenden, wenn ich:

  • möchte $IFSfür ein paar Befehle ändern , aber ich möchte nicht $IFSglobal für die aktuelle Shell ändern
  • cdirgendwo, aber ich möchte das $PWDfür die aktuelle Shell nicht ändern

Es ist zu beachten, dass Klammern in einer Funktionsdefinition verwendet werden können:

  • normale Verwendung: geschweifte Klammern: Funktionskörper wird in der aktuellen Shell ausgeführt; Nebenwirkungen bleiben nach Beendigung der Funktion bestehen

    $ count_tmp() { cd /tmp; files=(*); echo "${#files[@]}"; }
    $ pwd; count_tmp; pwd
    /home/jackman
    11
    /tmp
    $ echo "${#files[@]}"
    11    
    
  • ungewöhnliche Verwendung: Klammern: Funktionskörper wird in einer Subshell ausgeführt; Nebenwirkungen verschwinden, wenn die Subshell beendet wird

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

Dokumentation


11
Nach vielen Jahren der Shell-Entwicklung wusste ich nicht, dass Sie Klammern verwenden können, um Funktionen in Subshells auszuführen. Was für eine großartige Idee, den globalen Namespace nicht zu verschmutzen!
l0b0

7
Die Verwendung des localSchlüsselworts trägt wesentlich dazu bei, diese Verschmutzung zu beseitigen.
Glenn Jackman

2
Ja, aber Sie müssen daran denken, jede Variable local zu deklarieren, und der Code wird übersichtlich.
08.

4
Tipp: Wenn Sie nebenwirkungsfreie Funktionen wünschen, aber die ungewöhnliche Syntax der Funktionsdeklaration vermeiden möchten (die den Code-Editoren möglicherweise nicht bekannt ist), verwenden Sie statt der Deklaration nur Klammern beim Funktionsaufruf:pwd; (count_tmp); pwd;
Juve

2
zur Shell ... foo () (:;) ist äquivalent zu foo () {(:;); } So meldet es sich, wenn Sie fragen!
Anthony

23

Aus der offiziellen Bash-Dokumentation :

()

( list )

Wenn Sie eine Befehlsliste in Klammern setzen, wird eine Subshell-Umgebung erstellt und alle Befehle in der Liste in dieser Subshell ausgeführt. Da die Liste in einer Subshell ausgeführt wird, bleiben die Variablenzuweisungen nach Abschluss der Subshell nicht wirksam.

{}

{ list; }

Wenn Sie eine Befehlsliste in geschweifte Klammern setzen, wird die Liste im aktuellen Shell-Kontext ausgeführt. Es wird keine Subshell erstellt. Die folgende Liste mit Semikolon (oder Zeilenvorschub) ist erforderlich.


9

Code in '{}' wird im aktuellen Thread / Prozess / in der aktuellen Umgebung ausgeführt und Änderungen werden beibehalten. Um es kurz zu machen, der Code wird im aktuellen Bereich ausgeführt.
Code in '()' wird in einem separaten untergeordneten Prozess von bash ausgeführt, der nach der Ausführung verworfen wird. Dieser untergeordnete Prozess wird oft als Sub-Shell bezeichnet und kann als neuer, kindlicher Bereich betrachtet werden.

Betrachten Sie als Beispiel Folgendes ...

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

 ~ # 

Beachten Sie, dass im ersten Beispiel mit '{}' die Variable auch nach dem Schließen von '}' noch gesetzt ist, während im Beispiel mit '()' die Variable nicht außerhalb des Bereichs von '()' gesetzt ist.


4

(...)werden verwendet, um Code in einer Sub-Shell auszuführen. Code, der bei der Ausführung {...}verwendet wurde, wird in einer Sub-Shell nicht verwendet.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.