Tengo un script de shell llamado 'teleport.sh' como este:
if [ $1="1" ];
then
shift
mv "$@" ~/lab/Sun
elif [ $1="2" ];
then
shift
mv "$@" ~/lab/Moon
elif [ $1="3" ];
then
shift
mv "$@" ~/lab/Earth
fi
Cuando ejecuto:
sh teleport.sh 2 testfile
Esto testfilese mueve al ~/lab/Sundirectorio, lo que me confunde mucho ya que no pasé 1 o '1' a ese script.
¿Qué pasa aquí?

$var,$(cmd)e incluso`cmd`[a la que$(cmd)se debe preferir]). Hay algunos casos extremos en los que no tiene que citar, pero hacerlo siempre no le hará daño.$(cmd)es la sustitución de comandos , (principalmente) lo mismo que`cmd`. Ver mywiki.wooledge.org/CommandSubstitution y mywiki.wooledge.org/BashFAQ/082Respuestas:
Usar espacios soluciona tu problema.
Aunque esto es más ordenado:
fuente
$1="1"sintaxis original "funciona" (produciendo un resultado verdadero). ¿Cómo interpreta realmente[/testbuiltin esa expresión?testsolo ve un argumento (un "valor l"). Sin los otros argumentos (un "operador" y un "valor r"), no hay nada que probar, así quetestsolo dice "ok, bueno sí, me diste algo y eso debe ser completamente cierto".$1="1"es$1concatenado por=1La primera cosa obvia es que debe proporcionar espacios entre los argumentos de
[,testo[[:Cuando está en Bash,
[[ ]]se recomienda el uso, ya que no hace cosas innecesarias para la expresión condicional, como la división de palabras y la expansión de nombres de ruta. Citar alrededor de comillas dobles tampoco es necesario.==También se puede utilizar un operador más legible .Se agregó una nota: Si segundo operando también contiene variables, citando es necesario, ya que puede estar sujeta a la coincidencia de patrones si contiene caracteres reconocibles como
*,?,[], etc .. Si englobamiento extendido o coincidencia de patrones está habilitado conshopt -s extglob, otras formas como@(),!(), etc. También será reconocido como patrones. Ver coincidencia de patrones .Con operadores similares
<y>todavía puede ser necesario, ya que una vez me encontré con un error en el que no citar el segundo argumento causaba resultados diferentes.En cuanto al primer operando, no se aplica nada.
Considere también esta variación más simple:
O condensado:
"${@:2}"es una forma de expansión de subcadena o expansión de miembro de matriz donde2está el desplazamiento. Esto hace que la expansión comience en el segundo valor. Con esto puede que no necesitemos usarshift.El agregado
--impidemvreconocer nombres de archivo que comienzan con guión (-) como opciones no válidas.fuente
;&lugar de;;(ksh, bash, zsh solamente). Perobreakaún así no evita la caída,breakes solo salir de los bucles.ifsino para el[comando.[[ $foo == $bar ]]realizará la coincidencia de patrones, pero[[ $foo == "$bar" ]]no lo hará.Para responder a la pregunta de por qué sucede esto, este comportamiento de
[akatestestá documentado en POSIX :Le está pasando 1 argumento,
2=1que no es nulo y, por lo tanto,testsale con éxito.Como señalan otras publicaciones (y shellcheck ), si quisiera comparar por igualdad, en su lugar tendría que pasar los 3 argumentos
2,=y1.fuente
Solo quiero recomendar una alternativa portátil pero también más ordenada. Bash no es universal (y si no necesita universal, ¿por qué está escribiendo un script de shell?)
(Nota para los pedantes: sí, sé que las citas
$actionen lacase "$action" inlínea son innecesarias, pero creo que es mejor ponerlas allí de todos modos, para que los futuros lectores no tengan que recordar eso).fuente
/bin/shscripts portátiles , si lo necesita; de lo contrario, escriba en un lenguaje de script que sea menos terrible que el shell. De hecho, es más probable que el intérprete básico de Perl esté presente en entornos propietarios heredados y entornos integrados reducidos que Bash.