Quando usare () rispetto a {} in bash?

60

Sto studiando lo shell scripting con bash e ho bisogno di conoscere la differenza tra (...) e {...} . Come si fa a scegliere tra i due quando si scrive uno script?

    
posta Fat Mind 07.04.2015 - 16:22

4 risposte

79

Se vuoi che gli effetti collaterali dell'elenco comandi influiscano sulla tua corrente shell, usa {...}
Se vuoi eliminare gli effetti collaterali, usa (...)

Ad esempio, potrei usare una subshell se io:

  • vuoi modificare $IFS per alcuni comandi, ma non voglio alterare $IFS a livello globale per la shell corrente
  • cd da qualche parte, ma non voglio modificare $PWD per la shell corrente

Vale la pena notare che le parentesi possono essere utilizzate in una definizione di funzione:

  • utilizzo normale: parentesi: il corpo della funzione viene eseguito nella shell corrente; gli effetti collaterali rimangono dopo il completamento della funzione

    $ count_tmp() { cd /tmp; files=(*); echo "${#files[@]}"; }
    $ pwd; count_tmp; pwd
    /home/jackman
    11
    /tmp
    $ echo "${#files[@]}"
    11    
    
  • utilizzo inusuale: parentesi: il corpo della funzione viene eseguito in una subshell; gli effetti collaterali scompaiono quando subshell si chiude

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

Documentazione

    
risposta data glenn jackman 07.04.2015 - 16:40
21

Dalla documentazione di bash :

  

()

     
( list )
         

Se si posiziona un elenco di comandi tra parentesi, viene creato un ambiente di subshell e ognuno dei comandi in elenco deve essere eseguito in quella sottoshell. Poiché l'elenco viene eseguito in una subshell, le assegnazioni di variabili non rimangono attive dopo il completamento della sottoshell.

  
     

{}

     
{ list; }
         

L'inserimento di un elenco di comandi tra parentesi graffe fa sì che l'elenco venga eseguito nel contesto corrente della shell. Non è stata creata alcuna subshell. È necessario il seguente elenco di punti e virgola (o newline).

  
    
risposta data Digital Trauma 07.04.2015 - 21:45
9

Il codice in '{}' viene eseguito nel thread / processo / ambiente corrente e le modifiche vengono mantenute, per dirla in modo più sintetico, il codice viene eseguito nell'ambito corrente.
Il codice in '()' viene eseguito all'interno di un processo figlio separato di bash che viene scartato dopo l'esecuzione. Questo processo figlio viene spesso definito come sub-shell e può essere pensato come un nuovo ambito di tipo child.

Ad esempio, considera quanto segue ...

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

 ~ # 

Nel primo esempio, con '{}' la variabile è ancora impostata anche dopo la chiusura '}', mentre nell'esempio con '()' la variabile non è impostata al di fuori dell'ambito di '()'.

    
risposta data smokes2345 07.04.2015 - 18:53
4

(...) vengono utilizzati per eseguire il codice in una sottostruttura. Il codice usato tra parentesi {...} non verrà utilizzato in una sottostruttura.

    
risposta data Antoine Orsoni 07.04.2015 - 16:27

Leggi altre domande sui tag