2010-10-06 9 views
117

He visto bash scripts para la cadena de longitud distinta de cero de dos formas diferentes. La mayoría de los scripts utilizan la opción -n:

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

Pero la opción -n no es realmente necesario:

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

¿Cuál es la mejor manera?

mismo modo, que es el mejor modo para la prueba de longitud cero:

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

o

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

Respuesta

4

uso case/esac para probar

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

No, por favor. Esto no es para lo que 'case 'está destinado. – tbc0

277

Editar: Esto es una versión más completa que muestra más diferencias entre [ (también conocido como test) y [[.

La tabla siguiente muestra que si una variable está cotizada o no, si usa corchetes simples o dobles y si la variable contiene solo un espacio son las cosas que afectan si el uso de una prueba con o sin -n/-z es adecuado para verificar un variable.

 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 

Si desea saber si una variable no es cero longitud, realice cualquiera de los siguientes:

  • cita de la variable en soportes individuales (columna 2a)
  • uso -n y cotización la variable en soportes individuales (4a columna) soportes
  • uso dobles con o sin citar y con o sin -n (columnas 1b - 4b)

Observe en la columna 1a que comienza en la fila etiquetada "dos" que el resultado indica que [ está evaluando contenidos de la variable como si fueran parte de la expresión condicional (el resultado coincide con la afirmación implícita de la "T "o" F "en la columna de descripción). Cuando se usa [[ (columna 1b), el contenido variable se ve como una cadena y no se evalúa.

Los errores en las columnas 3a y 5a se deben a que el valor de la variable incluye un espacio y la variable no está citada. De nuevo, como se muestra en las columnas 3b y 5b, [[ evalúa el contenido de la variable como una cadena.

Si está utilizando [, la clave para asegurarse de no obtener resultados inesperados es citar la variable. Usando [[, no importa.

Los mensajes de error, que se suprimen, son "operador unario esperado" u "operador binario esperado".

Este es el script que produjo la tabla anterior.

#!/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 -r d t 
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  a b 
part a -a 
Tstr -n a 
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 
+9

wow ... muy buena explicación! +1 – jyz

+1

¡Gracias! Decidí adoptar el estilo de "citar la variable entre paréntesis (columna 2a)" IMO, la -n solo agrega ruido y disminuye la legibilidad. Del mismo modo, para la prueba de longitud cero o desarmado, usaré [! "$ var"] en lugar de [-z "$ var"]. – AllenHalsey

+1

Entonces su tabla para '[" 'vs' [-n "' (la primera pregunta del OP) muestra que son completamente equivalentes, ¿no? – hobs

6

Estas son algunas pruebas más

Verdadero si la cadena no está vacía:

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

Verdadero si la cadena está vacía:

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

Un modo alternativo y tal vez más transparente de evaluar una variable de env vacía es usar ...

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

Esto es muy vieja escuela de los días de shell de Bourne. No perpetúes este viejo hábito. 'bash' es una herramienta más nítida que sus predecesores. – tbc0

Cuestiones relacionadas