2012-11-24 23 views
103

Sto leggendo esempi bash su if ma alcuni esempi sono scritti con le singole parentesi quadre:Qual è la differenza tra parentesi quadre singole e doppie in Bash?

if [ -f $param ] 
then 
    #... 
fi 

altri con doppie parentesi quadre:

if [[ $? -ne 0 ]] 
then 
    start looking for errors in yourlog 
fi 

Qual è la differenza?

+2

È possibile ottenere la vostra risposta, cercando in risposta a questa domanda: http://unix.stackexchange.com/questions/3831/in- bash-is-if-z-1-and-if-1-the-same –

+0

http://serverfault.com/questions/52034/what-is-the-difference-between-double-and-single-square- brackets-in-bash –

risposta

124

I singoli [] sono test di condizioni conformi alla shell posix.

Double [[]] sono un'estensione allo standard [] e sono supportati da bash e altre shell (ad esempio zsh, ksh). Supportano operazioni extra (così come le operazioni di posix standard). Ad esempio: || anziché -o ed espressioni regolari corrispondenti a =~. Un elenco più completo delle differenze può essere trovato nel bash manual section on conditional constructs.

Utilizzare [] ogni volta che si desidera che lo script sia trasferibile attraverso le shell. Utilizzare [[]] se si desidera che le espressioni condizionali non siano supportate da [] e che non sia necessario trasferirle.

1

è possibile utilizzare le doppie parentesi quadre per la luce corrispondenza regex, per esempio :

if [[ $1 =~ "foo.*bar" ]] ; then

(fino a quando la versione di bash si utilizza supporti questa sintassi)

+5

Tranne che hai citato il pattern, quindi ora viene trattato come una stringa letterale. – ormaaj

+0

molto vero. a volte questo mi infastidisce :) – asf107

13

All'interno singole staffe per condizione di prova (ad esempio [...]), alcuni operatori come singolo = è supportato da tutte le shell, mentre l'uso dell'operatore == non è supportato da alcune delle shell precedenti.

Dentro doppie parentesi per test di condizioni (cioè [[...]]), non vi è alcuna differenza tra l'utilizzo di = o == in shell vecchie o nuove.

Modifica: Devo anche notare che: In bash, usare sempre parentesi quadre [[...]] se possibile, perché è più sicuro delle parentesi singole. Illustrerò il motivo per cui con il seguente esempio:

if [ $var == "hello" ]; then 

se $ var capita di essere nullo/vuoto, allora questo è ciò che lo script vede:

if [ == "hello" ]; then 

che romperà lo script. La soluzione è utilizzare entrambe le parentesi doppie o ricordarsi sempre di mettere le virgolette attorno alle variabili ("$var"). Le doppie parentesi rappresentano una pratica di codifica difensiva migliore.

45

differenze di comportamento

Testato in Bash 4.3.11:

  • POSIX vs estensione Bash:

  • comando regolare vs magia

    • [ è solo un comando regolare con un nome strano.

      ] è solo un argomento di [ che impedisce l'utilizzo di ulteriori argomenti.

      Ubuntu 16.04 ha in realtà un eseguibile per esso a fornito da coreutils, ma la versione incorporata di bash ha la precedenza.

      Nulla viene modificato nel modo in cui Bash analizza il comando.

      In particolare, è < reindirizzamento, && e || concatenare più comandi, () genera subshells meno sfuggito dalla \, ed espansione parola avviene come di consueto.

    • [[ X ]] è un singolo costrutto che rende magistralmente analizzato X. <, &&, || e () vengono trattati in modo speciale e le regole di suddivisione in parole sono diverse.

      Ci sono anche altre differenze come = e =~.

  • <

    • [[ a < b ]]: Confronto lexicographical
    • [ a \< b ]: Idem come sopra. \ richiesto oppure esegue il reindirizzamento come per qualsiasi altro comando. Estensione Bash.
    • non riuscivo a trovare un POSIX alternativa a questo, si veda: How to test strings for less than or equal?
  • && e ||

    • [[ a = a && b = b ]]: vero, logico e
    • [ a = a && b = b ]: errore di sintassi, && analizzato come AND command separator cmd1 && cmd2
    • [ a = a -a b = b ]: equivalente, ma sconsigliata in POSIX
    • [ a = a ] && [ b = b ]: POSIX raccomandazione
  • (

    • [[ (a = a || a = b) && a = b ]]: false
    • [ (a = a) ]: errore di sintassi, () viene interpretato come subshell
    • [ \(a = a -o a = b \) -a a = b ]: equivalente , ma () è deprecato da POSIX
    • ([ a = a ] || [ a = b ]) && [ a = b ] raccomandazione POSIX
  • suddivisione delle parole

    • x='a b'; [[ $x = 'a b' ]]: è vero, non citazioni necessario
    • x='a b'; [ $x = 'a b' ]: errore di sintassi, si espande a [ a b = 'a b' ]
    • x='a b'; [ "$x" = 'a b' ]: equivalente
  • =

    • [[ ab = a? ]]: vero, perché lo fa pattern matching (* ? [ sono magia). Non glob si espande nei file nella directory corrente.
    • [ ab = a? ]: a? glob si espande. Quindi può essere vero o falso a seconda dei file nella directory corrente.
    • [ ab = a\? ]: false, non glob espansione
    • = e == sono gli stessi sia [ e [[, ma == è un'estensione Bash.
    • printf 'ab' | grep -Eq 'a.': POSIX ERE equivalente
    • [[ ab =~ 'ab?' ]]: false, perde la magia con ''
    • [[ ab? =~ 'ab?' ]]: vero
  • =~

    • [[ ab =~ ab? ]]: vero, POSIX extended regular expression partita, ? non lo fa glob expand
    • [ a =~ a ]: errore di sintassi
    • printf 'ab' | grep -Eq 'ab?': POSIX equivalente

Raccomandazione

preferisco usare sempre [].

Esistono POSIX equivalenti per ogni costrutto [[ ]] che ho visto.

Se si utilizza [[ ]] voi:

  • perdere portabilità
  • forza il lettore a imparare la complessità di un altro interno bash. [ è solo un normale comando con un nome strano, nessuna semantica speciale è coinvolta.
+1

"* Esistono POSIX equivalenti per ogni [[]] costrutto che ho visto. *" La stessa cosa si può dire di qualsiasi [Turing completo] (https: //en.wikipedia. org/wiki/Universal_Turing_machine) linguaggio sulla faccia del pianeta. –

+1

@ A.Rick che sarebbe una risposta valida a tutti "Come fare X nel linguaggio Y" QUINDI domande :-) Certamente, c'è un implicito "convenientemente" in quella affermazione. –

+2

Sommario fantastico. Grazie per lo sforzo. Tuttavia non sono d'accordo con la raccomandazione. È portabilità contro sintassi più coerente e potente. Se è possibile richiedere bash> 4 nei propri ambienti, si consiglia la sintassi [[]]. – Alkaline

1

Bash manual dice:

quando viene utilizzato con [[, gli operatori ‘<’ e ‘>’ sorta lessicograficamente utilizzando il locale corrente. Il comando test utilizza l'ordinamento ASCII .

(Il comando test è identica a [])

Problemi correlati