Prova per stringa di lunghezza diversa da zero in Bash: o

Ho visto gli script di bash testare la stringa di lunghezza diversa da zero in due modi diversi. La maggior parte degli script usa l’opzione -n:

#!/bin/bash # With the -n option if [ -n "$var" ]; then # Do something when var is non-zero length fi 

Ma l’opzione -n ​​non è veramente necessaria:

 # Without the -n option if [ "$var" ]; then # Do something when var is non-zero length fi 

Qual è il modo migliore?

Allo stesso modo, qual è il modo migliore per testare a lunghezza zero:

 if [ -z "$var" ]; then # Do something when var is zero-length fi 

o

 if [ ! "$var" ]; then # Do something when var is zero-length fi 

Modifica: questa è una versione più completa che mostra più differenze tra [ (aka test ) e [[ .

La seguente tabella mostra che se una variabile è quotata o meno, se si usano parentesi singole o doppie e se la variabile contiene solo uno spazio sono le cose che influiscono sull’utilizzo di un test con o senza -n/-z è adatto per controllare un variabile.

  1a 2a 3a 4a 5a 6a |1b 2b 3b 4b 5b 6b [ [" [-n [-n" [-z [-z" |[[ [[" [[-n [[-n" [[-z [[-z" unset: false false true false true true |false false false false true true null : false false true false true true |false false false false true true space: false true true true true false |true true true true false false zero : true true true true false false |true true true true false false digit: true true true true false false |true true true true false false char : true true true true false false |true true true true false false hyphn: true true true true false false |true true true true false false two : -err- true -err- true -err- false |true true true true false false part : -err- true -err- true -err- false |true true true true false false Tstr : true true -err- true -err- false |true true true true false false Fsym : false true -err- true -err- false |true true true true false false T= : true true -err- true -err- false |true true true true false false F= : false true -err- true -err- false |true true true true false false T!= : true true -err- true -err- false |true true true true false false F!= : false true -err- true -err- false |true true true true false false Teq : true true -err- true -err- false |true true true true false false Feq : false true -err- true -err- false |true true true true false false Tne : true true -err- true -err- false |true true true true false false Fne : false true -err- true -err- false |true true true true false false 

Se vuoi sapere se una variabile ha una lunghezza diversa da zero, fai una delle seguenti azioni:

  • citare la variabile tra parentesi (colonna 2a)
  • usa -n e cita la variabile tra parentesi (colonna 4a)
  • usa doppie parentesi con o senza virgolette e con o senza -n (colonne 1b – 4b)

Si noti nella colonna 1a che inizia con la riga “due” che il risultato indica che [ sta valutando il contenuto della variabile come se facessero parte dell’espressione condizionale (il risultato corrisponde all’asserzione implicita dalla “T” o “F” nella colonna della descrizione). Quando [[ è usato (colonna 1b), il contenuto della variabile è visto come una stringa e non valutato.

Gli errori nelle colonne 3a e 5a sono causati dal fatto che il valore della variabile include uno spazio e la variabile non è quotata. Di nuovo, come mostrato nelle colonne 3b e 5b, [[ valuta il contenuto della variabile come una stringa.

Se stai usando [ , la chiave per assicurarti di non ottenere risultati inattesi è di quotare la variabile. Usando [[ , non importa.

I messaggi di errore, che vengono soppressi, sono “operatore unario previsto” o “operatore binario previsto”.

Questo è lo script che ha prodotto la tabella sopra.

 #!/bin/bash # by Dennis Williamson # 2010-10-06, revised 2010-11-10 # for http://stackoverflow.com/questions/3869072/test-for-non-zero-length-string-in-bash-n-var-or-var # designed to fit an 80 character terminal dw=5 # description column width w=6 # table column width t () { printf "%-${w}s" "true"; } f () { [[ $? == 1 ]] && printf "%-${w}s" "false " || printf "%-${w}s" "-err- "; } o=/dev/null echo ' 1a 2a 3a 4a 5a 6a |1b 2b 3b 4b 5b 6b' echo ' [ [" [-n [-n" [-z [-z" |[[ [[" [[-n [[-n" [[-z [[-z"' while read -rdt do printf "%-${dw}s: " "$d" case $d in unset) unset t ;; space) t=' ' ;; esac [ $t ] 2>$o && t || f [ "$t" ] && t || f [ -n $t ] 2>$o && t || f [ -n "$t" ] && t || f [ -z $t ] 2>$o && t || f [ -z "$t" ] && t || f echo -n "|" [[ $t ]] && t || f [[ "$t" ]] && t || f [[ -n $t ]] && t || f [[ -n "$t" ]] && t || f [[ -z $t ]] && t || f [[ -z "$t" ]] && t || f echo done <<'EOF' unset null space zero 0 digit 1 char c hyphn -z two ab part a -a Tstr -na Fsym -h . T= 1 = 1 F= 1 = 2 T!= 1 != 2 F!= 1 != 1 Teq 1 -eq 1 Feq 1 -eq 2 Tne 1 -ne 2 Fne 1 -ne 1 EOF 

Ecco alcuni altri test

Vero se la stringa non è vuota:

 [ -n "$var" ] [[ -n $var ]] test -n "$var" [ "$var" ] [[ $var ]] (( ${#var} )) let ${#var} test "$var" 

Vero se la stringa è vuota:

 [ -z "$var" ] [[ -z $var ]] test -z "$var" ! [ "$var" ] ! [[ $var ]] ! (( ${#var} )) ! let ${#var} ! test "$var" 

Pubblicare questa risposta poiché questo post è contrassegnato come bash.

È meglio usare il più potente [[ quanto riguarda Bash.

Casi usuali

 if [[ $var ]]; then # var is set and it is not empty if [[ ! $var ]]; then # var is not set or it is set to an empty string 

I due precedenti costrutti sembrano puliti e leggibili. Dovrebbero bastare nella maggior parte dei casi.

Si noti che non è necessario citare le espansioni variabili all’interno [[ poiché non vi è alcun pericolo di divisione delle parole e globbing .

Casi rari

Nel raro caso in cui dovessimo fare una distinzione tra “essere impostato su una stringa vuota” e “non essere impostato affatto”, potremmo usare questi:

 if [[ ${var+x} ]]; then # var is set but it could be empty if [[ ! ${var+x} ]]; then # var is not set if [[ ${var+x} && ! $var ]]; then # var is set and is empty 

Possiamo anche usare il test -v :

 if [[ -v var ]]; then # var is set but it could be empty if [[ ! -v var ]]; then # var is not set if [[ -v var && ! $var ]]; then # var is set and is empty 

Più discussione

Ci sono un sacco di domande e risposte relative a questo. Eccone alcuni:

  • Come verificare se una variabile è impostata in Bash?
  • Come scoprire se una variabile è vuota o meno in Bash
  • Le doppie parentesi quadre [[]] sono preferibili rispetto alle parentesi quadre [] in Bash?
  • Qual è la differenza tra parentesi quadre singole e doppie in Bash?
  • Un’ottima risposta di mklement0 in cui parla di [[ vs [
  • Bash Hackers Wiki – [ vs [[

utilizzare case/esac per testare

 case "$var" in "") echo "zero length";; esac 

Un modo alternativo e forse più trasparente di valutare una variabile env vuota è usare …

  if [ "x$ENV_VARIABLE" != "x" ] ; then echo 'ENV_VARIABLE contains something' fi 

La risposta corretta è la seguente:

 if [[ -n $var ]] ; then blah fi 

Nota l’uso di [[...]] , che gestisce correttamente la citazione delle variabili per te.