¿Cómo verificar si $ 1 y $ 2 son nulos?

41

Estoy ejecutando un script que pasa el argumento de cadena y quiero hacer si la instrucción else se muestra a continuación:

if [ $1 != '' ] && [ $2 != '' ]
then 
    do something.....

Pero se muestra Error too many argument. ¿Por qué?

taymindis Woon
fuente
Debe proporcionar 1. el comando al que llama el script y 2. la salida completa.
Lucio
2
Debe utilizar [[ ]]. De lo contrario, debe citar sus variables.
Christophe De Troyer
Si $ 1 no existiera, entonces $ 2 se convertiría en $ 1, lo que hace que la prueba de $ 1 y $ 2 sean nulos y parezca irrelevante.
WinEunuuchs2Unix
@ WinEunuuchs2Unix No necesariamente irrelevante: en algunos casos, desea asegurarse de que realmente haya algo en lugar de una cadena en blanco o nula en los argumentos. $1podría ser desarmado o establecido en una cadena nula por el usuario del script. Considere esta secuencia de comando: $ set '' barentonces echo "x${1}x";Ambas variables están establecidas, pero una de ellas es nula.
Sergiy Kolodyazhnyy

Respuestas:

56

Intente usar la prueba -z:

if [ -z "$1" ] && [ -z "$2" ]

Del hombre bash:

-z string
   True if the length of string is zero.
Sylvain Pineau
fuente
¡Esto funciona para mi!
pengisgood
Es interesante que la respuesta más votada y aceptada no responda realmente a la pregunta formulada.
mehmet
Al escribir scripts de shell portátiles, este indicador debe usarse con cuidado, ya que en ciertos Unix comerciales, este indicador es defectuoso. Vea mi respuesta para las fuentes vinculadas.
Sergiy Kolodyazhnyy
14

Como esto está etiquetado bash, recomiendo que uno use la construcción de prueba extendida ( [[...]]) y olvide las comillas:

if [[ -z $1 && -z $2 ]]; then
...

A menos que vaya por shcompatibilidad / POSIX, no hay razón para no usar [[ ]].

muru
fuente
3

Lo siguiente también funciona,

if [ "$1" == "" && "$2" == ""]; then
    echo NULL
fi
Avinash Raj
fuente
El &&y otros separadores de comandos lógicos no están permitidos en el clásico test. Tienes que usar otras construcciones de prueba en su lugar (como -a, creo)
muru
3

Para la versión anterior de la respuesta, vea la segunda parte de esta respuesta. Si desea conocer los detalles, siga leyendo

La causa del problema

En la pregunta en sí, se informa que OP ve too many arguments error, que cuando se prueba bashno parece ser el caso:

$ [ $1 != '' ] && [ $2 != '' ]
bash: [: !=: unary operator expected

Con lo /bin/shque en realidad está vinculado a /bin/dashUbuntu, el error se informa de la siguiente manera:

$ sh
$ [ $1 != '' ] && [ $2 != '' ]
sh: 1: [: !=: unexpected operator

Y el independiente /bin/testtambién:

$ /usr/bin/test $1 != ''  
/usr/bin/test: missing argument after ‘’

Nota al margen: si se pregunta qué es /usr/bin/testy por qué estoy usando bashy sh, entonces debe saber que [es un alias para el testcomando, que también existe como ejecutable independiente o más comúnmente, como shell incorporado, que es lo que cada shell usará primero . En cuanto a las ifdeclaraciones, operan en las estatuas de salida de los comandos, por lo tanto, por qué [y testson comandos, y todo lo demás son argumentos para esos comandos: el orden incorrecto de esos argumentos de la línea de comandos conduce a errores.

Volviendo al tema: no está claro cómo OP obtuvo el error no relacionado. Sin embargo, en los 3 casos el problema es el mismo: la variable no establecida se tratará como vacía, por lo tanto, lo que el shell ve con estas variables no citadas es

[ != '' ]

que rompe la sintaxis que testentiende. ¿Recuerdas lo que dije sobre el orden incorrecto de los argumentos de la línea de comandos? Por eso es importante citar. Habilitemos la salida de diagnóstico y veamos qué shell se ejecuta:

$ set -x
# throws error
$ [ $1 != '' ] && [ $2 != '' ] 
+ '[' '!=' '' ']'
bash: [: !=: unary operator expected
# no error
$ [ "$1" != '' ] && [ "$2" != '' ] || echo null vars
+ '[' '' '!=' '' ']'
+ echo null vars
null vars

Mejor manera de probar variables no establecidas

Un enfoque muy frecuente que ves alrededor es este:

 if [ "x$var1" == "x"  ] && [ "x$var2" == "x"  ];                                                                
 then
     echo "both variables are null"
 fi

Para citar a Gilles :

En ["x $ 1" = "x"], el prefijo x asegura que x "$ 1" no pueda parecer un operador, por lo que la única forma en que el shell puede analizar esta prueba es tratando a = como un operador binario.

Presumiblemente, esto debería ser bastante portátil ya que los he visto en /bin/shscripts. También se puede combinar como en

if [ "x${var1}${var2}" == "x" ]; then
    ...
fi

Por supuesto, podríamos usar la -zbandera, sin embargo, según la investigación en algunos shells, particularmente ksh88 (según Stephane Chazelas ), esta bandera es defectuosa.

Ver también

Sergiy Kolodyazhnyy
fuente
+1 para un enfoque muy interesante.
WinEunuuchs2Unix
@ WinEunuuchs2Unix Editado para hacerlo aún más interesante :)
Sergiy Kolodyazhnyy
1

Creo que el título de la publicación no es exacto, ya que la intención en el mensaje era verificar si $ 1 y $ 2 no son nulos. El ejemplo dado solo faltaba comillas dobles en $ 1 y $ 2 para funcionar. Las variables deben estar entre comillas dobles para expandirse al comparar cadenas. Pero verificar si existen $ 1 y $ 2 es lo mismo que verificar si existen $ 2, ya que no puede existir si $ 1 no existe. El comando 'if' tampoco es necesario en este caso, ya que 'test' devuelve verdadero / falso y usa '&&' como 'entonces' si return es 0 / verdadero:

[ "$2" != '' ] && commands...

Más simple, con -n (distinto de cero):

[ -n "$2" ] && commands...

"Verificar si $ 1 y $ 2 son nulos" sería lo mismo que verificar si no hay ningún parámetro:

[ $# -eq 0 ] && commands...
Guariba Som
fuente