Comparación de cadenas en bash. [[: extraviado

166

Estoy tratando de comparar cadenas en bash. Ya encontré una respuesta sobre cómo hacerlo en stackoverflow . En el script que estoy intentando, estoy usando el código enviado por Adam en la pregunta mencionada:

#!/bin/bash
string='My string';

if [[ "$string" == *My* ]]
then
  echo "It's there!";
fi

needle='y s'
if [[ "$string" == *"$needle"* ]]; then
  echo "haystack '$string' contains needle '$needle'"
fi

También probé el enfoque de ubuntuforums que puedes encontrar en la segunda publicación

if [[ $var =~ regexp ]]; then
  #do something
fi

En ambos casos recibo un error:

[[: not found

¿Qué estoy haciendo mal?

user1581900
fuente
Podría hacerlo mal, pero usar un solo corchete siempre funcionó para mí.
Markus Unterwaditzer
1
¿Qué /bin/bash --versionimprime?
themel
44
[no funcionará en este caso, porque no admite patrones.
Ansgar Wiechers

Respuestas:

158

[[es un bash-builtin. Tu /bin/bashno parece ser una fiesta real.

De un comentario:

Agregar #!/bin/bashen la parte superior del archivo

Ansgar Wiechers
fuente
si
escribo
55
¿Obtienes el mismo resultado cuando corres /bin/bash -c "type [["?
Ansgar Wiechers
43
Esto me sucedió porque olvidé agregar #!/bin/bashen la parte superior de mi archivo
morpático
12
Pasé a mí porque ejecuté el script con shmucha frustración. Ahora solo tengo que rehacer todo lo que deshice antes de encontrar esta respuesta.
Louis Loudog Trottier
174

¿Cómo estás ejecutando tu script? Si lo hicieras con

$ sh myscript

Deberías intentarlo:

$ bash myscript

o, si el script es ejecutable:

$ ./myscript

sh y bash son dos conchas diferentes . Mientras que en el primer caso pasa su guión como argumento al intérprete sh, en el segundo caso decide en la primera línea qué intérprete se utilizará.

Akos K
fuente
obtuve permiso denegado de esta manera. con sudo ./myscript su comando no encontrado
user1581900
11
hacer chmod + x myscript , luego ejecutar de nuevo, no necesitas sudo
Akos K
2
¿Cómo estás invocando tu guión?
Akos K
Como dijiste. normalmente lo llamo con '$ sh myscipt.sh'. 2da vez después de hacer chmod + x myscript.sh lo llamé con ./myscript.sh
user1581900
55
Se espera el error cuando ejecuta el script vía sh myscript.sh, porque /bin/shemula un shell Bourne donde [[no está integrado. Sin embargo, ejecutar el script vía ./script.shno debería producir un error, porque en ese caso el shebang debería hacer /bin/bashque se use.
Ansgar Wiechers
81

Es la primera línea en tu script:

#!/bin/bash

o

#!/bin/sh

el shell sh produce estos mensajes de error, no bash

Wiley
fuente
1
¡También me faltaba la primera línea para producir el error que mencionó el autor!
Anónimo
14

Tuve este problema al instalar Heroku Toolbelt

Así es como resolví el problema.

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 ago 15  2012 /bin/sh -> dash

Como puede ver, / bin / sh es un enlace a "guión" (no bash), y [[es azucar sintáctico bash. Así que acabo de reemplazar el enlace a / bin / bash. ¡Tenga cuidado al usar rm como este en su sistema!

$ sudo rm /bin/sh
$ sudo ln -s /bin/bash /bin/sh
jperelli
fuente
66
Anular el valor predeterminado shpara su distribución es mal aconsejado en mi humilde opinión. Un shell con el que se ejecuta shdebería funcionar dash; si no es así, eso es un error en el guión. Si necesita bashfunciones, use bash, no sh.
tripleee
44
esto suena terrible
tbh
2
Estoy de acuerdo, fue solo una solución fea. Una solución similar pero mejor sería usar update-alternatives(en debian-based-linux) como este justinconover.wordpress.com/2012/05/14/… pero al final, sería lo mismo.
jperelli
13

Como @Ansgar mencionó, [[es un bashism, es decir, integrado en Bash y no está disponible para otros shells. Si quieres que tu script sea portátil, úsalo [. Las comparaciones también necesitarán una sintaxis diferente: cambiar ==a =.

Amedee Van Gasse
fuente
Comprobé un poco con Ubuntu 16.04 y (sh ->) dash 0.5.8-2.1ubuntu2 y descubrí que [funciona bien en combinación con "-eq" y similares. Se puede encontrar información similar sobre operadores de comparación para este contexto aquí: stackoverflow.com/questions/10849297/… - Realicé una búsqueda adicional con el operador de evaluación (()) como se recomienda en el siguiente enlace, pero eso pareció fallar para mis cambios invasivos mínimos / o / necesitaría un nivel mucho más profundo de cambios de código. softpanorama.org/Scripting/Shellorama/Control_structures/…
Alexander Stohr
3

Especifique bash en lugar de sh cuando ejecute el script. Personalmente noté que son diferentes en Ubuntu 12.10:

bash script.sh arg0 ... argn

Smeterlink
fuente
¡Esto me lo arregló!
Djamillah