not - if linux bash
Significado del error "[: demasiados argumentos" de if[](corchetes) (3)
No pude encontrar ningún recurso directo simple que explicara el significado y la solución para el siguiente error de BASH shell, por lo que estoy publicando lo que encontré después de investigarlo.
El error:
-bash: [: too many arguments
Versión amigable para Google: bash open square bracket colon too many arguments
.
Contexto: una condición if en corchetes simples con un operador de comparación simple como equals, greater than etc, por ejemplo:
VARIABLE=$(/some/command);
if [ $VARIABLE == 0 ]; then
# some action
fi
Acabo de tropezar con esta publicación, obteniendo el mismo error, tratando de probar si dos variables están vacías (o no). Eso resulta ser una comparación compuesta - 7.3. Otros operadores de comparación: guía avanzada Bash-Scripting ; y pensé que debería notar lo siguiente:
- Utilicé
que significa "vacío" al principio; pero eso significa que "el archivo existe" - use-e
-z
para probar la variable vacía (cadena) - Las variables de cadena deben ser citadas
- Para la comparación Y lógica compuesta, o bien:
- use dos
test
sy&&
them:[ ... ] && [ ... ]
- o use el operador
-a
en una solatest
:[ ... -a ... ]
- use dos
Aquí hay un comando de trabajo (buscando a través de todos los archivos txt en un directorio, y volcando aquellos que grep
encuentra contienen ambas palabras):
find /usr/share/doc -name ''*.txt'' | while read file; do /
a1=$(grep -H "description" $file); /
a2=$(grep -H "changes" $file); /
[ ! -z "$a1" -a ! -z "$a2" ] && echo -e "$a1 /n $a2" ; /
done
edición 12 aug 2013: nota relacionada con el problema:
tenga en cuenta que al verificar la igualdad de cadena con la test
clásica (corchete simple [
), DEBE tener un espacio entre el operador "es igual", que en este caso es un singe "igual" =
signo (aunque dos signos iguales ==
parecen para ser aceptado como operador de igualdad también). Por lo tanto, esto falla (en silencio):
$ if [ "1"=="" ] ; then echo A; else echo B; fi
A
$ if [ "1"="" ] ; then echo A; else echo B; fi
A
$ if [ "1"="" ] && [ "1"="1" ] ; then echo A; else echo B; fi
A
$ if [ "1"=="" ] && [ "1"=="1" ] ; then echo A; else echo B; fi
A
... pero agrega el espacio, y todo se ve bien:
$ if [ "1" = "" ] ; then echo A; else echo B; fi
B
$ if [ "1" == "" ] ; then echo A; else echo B; fi
B
$ if [ "1" = "" -a "1" = "1" ] ; then echo A; else echo B; fi
B
$ if [ "1" == "" -a "1" == "1" ] ; then echo A; else echo B; fi
B
He tenido el mismo problema con mis scripts. Pero cuando hice algunas modificaciones funcionó para mí. Me gustó esto:
export k=$(date "+%k");
if [ $k -ge 16 ]
then exit 0;
else
echo "good job for nothing";
fi;
de esa manera resolví mi problema. Espero que te ayude también.
Si su $VARIABLE
es una cadena que contiene espacios u otros caracteres especiales, y se utilizan corchetes simples (que es un atajo para el comando de test
), la secuencia se puede dividir en varias palabras. Cada uno de estos se trata como un argumento separado.
Entonces esa variable se divide en muchos argumentos :
VARIABLE=$(/some/command);
# returns "hello world"
if [ $VARIABLE == 0 ]; then
# fails as if you wrote:
# if [ hello world == 0 ]
fi
Lo mismo ocurrirá con cualquier llamada a función que coloque una cadena que contenga espacios u otros caracteres especiales.
Arreglo fácil
Ajustar el resultado variable entre comillas dobles, forzándolo a permanecer como una cadena (por lo tanto, un argumento). Por ejemplo,
VARIABLE=$(/some/command);
if [ "$VARIABLE" == 0 ]; then
# some action
fi
Simple como eso. Pero salte a "También tenga cuidado ..." a continuación si no puede garantizar que su variable no sea una cadena vacía, o una cadena que contenga nada más que espacios en blanco.
O bien, una solución alternativa es usar corchetes dobles (que es un atajo para el new test
comando de new test
).
Sin embargo, esto solo existe en bash (y aparentemente korn y zsh), por lo que puede no ser compatible con los shells predeterminados llamados por /bin/sh
etc. Esto significa que en algunos sistemas, por ejemplo, podría funcionar desde la consola pero no desde cron
, según cómo esté configurado todo.
Se vería así:
VARIABLE=$(/some/command);
if [[ $VARIABLE == 0 ]]; then
# some action
fi
También tenga cuidado con el [: unary operator expected
error [: unary operator expected
Si ve el error de "demasiados argumentos", es probable que obtenga una cadena de una función con resultados impredecibles. Si también es posible obtener una cadena vacía (o toda la cadena de espacio en blanco), esto se trataría como cero argumentos incluso con la "solución rápida" anterior, y fallaría con [: unary operator expected
Es lo mismo ''gotcha'' si está acostumbrado a otros idiomas: no espera que el contenido de una variable se imprima efectivamente en el código como este antes de que se evalúe.
Aquí hay un ejemplo que evita tanto el [: too many arguments
como el [: unary operator expected
errores [: unary operator expected
: reemplazando el resultado con un valor predeterminado si está vacío (en este ejemplo, 0
), con comillas dobles para todo el asunto:
VARIABLE=$(/some/command);
if [ "${VARIABLE:-0}" == 0 ]; then
# some action
fi
(aquí, la acción ocurrirá si $ VARIABLE es 0 o está vacío. Naturalmente, debe cambiar el 0 (el valor predeterminado) a un valor predeterminado diferente si se desea un comportamiento diferente)
Nota final: dado que [
es un atajo para la test
, todo lo anterior también es cierto para la test: too many arguments
error test: too many arguments
(y también test: unary operator expected
)