¿Por qué `==` se comporta de manera diferente dentro de `[...]` en zsh y bash?

9

Obtengo lo que esperaba al hacer esto en bash:

[ "a" == "a" ] && echo yes

Me dio yes.

Pero cuando hago esto zsh, obtengo lo siguiente:

zsh: = not found

¿Por qué el mismo comando ( /usr/bin/[) se comporta de manera diferente en diferentes shells?

Johnson Steward
fuente
55
no es el mismo comando: es un valor incorporado que se encuentra antes de buscarlo $PATH. y ==no es una testsintaxis válida para /usr/bin/[anway. Solo =esta bien.
mikeserv

Respuestas:

18

No está /usr/bin/[en ninguno de los depósitos. En Bash, está utilizando el comando / incorporadotest[ , y de manera similar en zsh .

La diferencia es que zsh también tiene una =expansión : se =fooexpande a la ruta al fooejecutable. Eso significa que ==se trata de tratar de encontrar un comando llamado =en suPATH . Como ese comando no existe, obtienes el error

zsh: = not found

que viste (y de hecho, esto mismo sucedería incluso si realmente estuvieras usando /usr/bin/[).


Usted puede utilizar ==aquí si realmente quiere. Esto funciona como esperaba en zsh:

[ "a" "==" "a" ] && echo yes

porque la cita impide que se =wordejecute la expansión. También puede deshabilitar la equalsopción con setopt noequals.


Sin embargo, sería mejor tampoco:

  • Usando single =, la prueba de igualdad compatible con POSIX ; o
  • Mejor aún, el uso de los [[condicionales con== tanto golpe y zsh . En general, [[es mejor y más seguro en todos los aspectos, incluido el evitar este tipo de problema (y otros) al tener reglas de análisis especiales en su interior.
Michael Homer
fuente
¿Cuál es la diferencia exacta entre [y [[? (Buscar en Google solo [ vs [[me da resultados vs, LOL)
Johnson Steward
2
[[admite una gama más amplia de pruebas en ambos casos y tiene reglas de análisis personalizadas que evitan la necesidad de citar variables, operadores, etc. Si está utilizando específicamente Bash o zsh, úselo [[. Si está escribiendo un script portátil, escriba en el comando [/ testcomando compatible con POSIX (que puede o no ser un comando real en su sistema en ejecución).
Michael Homer
1
Solo use [[allí y olvide [existe.
Michael Homer
1
ya sabes ... no estoy de acuerdo con tu recomendación. [[es diferente capaz probar esto con ella: for f in *; do [ -e "$f" ] && for a in f d h p S b c; do [ "-$a" "$f" ] && for p in r w x u g; do [ "-$p" "$f" ] || p=-; a=$a$p; done && break; done && printf "%s:\t%s\n" "$a" "$f"; done.
mikeserv
3
Bueno, =/ ==es sin duda uno de los casos en que [[no es mejor que [, como [[ a == b ]]es lo hace "a" coincidir con el patrón "B" y no es "a" igual a "b" como era de esperar. Eso significa que necesitas escribir, [[ $a == "$b" ]]por ejemplo. Al menos, con el [comando, si sabe cómo funciona el análisis de comandos, sabe que debe escribirlo [ "$a" = "$b" ]para evitar el operador split + glob como en otros comandos. Con eso en mente y si no usa -a o -o, [es seguro en implementaciones conformes con POSIX.
Stéphane Chazelas
2

Y zsh y bash dan la misma respuesta (también typeestá integrado para ambos shells):

$ type -a [
[ is a shell builtin
[ is /usr/bin/[
Jshura
fuente
2

[ es un comando integrado de shell en bash y en zsh:

$ type [
[ is a shell builtin

De la documentación de Shell Builtin Commands :

Los comandos incorporados están contenidos dentro del propio shell . Cuando el nombre de un comando incorporado se usa como la primera palabra de un comando simple (vea Comandos simples ), el shell ejecuta el comando directamente, sin invocar otro programa. Los comandos incorporados son necesarios para implementar funcionalidades imposibles o inconvenientes de obtener con utilidades separadas.

La documentación oficial ( $ help test) solo permite utilizar =:

STRING1 = STRING2

Es cierto si las cadenas son iguales.

Entonces, la expresión correcta sería:

$ [ "a" = "a" ] && echo yes
yes

Lo que sucede es que bash es un poco menos estricto. Apoyar al ==operador con [ parece ser una extensión bash y no se recomienda usarlo:

cadena1 == cadena2

cadena1 = cadena2

Es cierto si las cadenas son iguales. Cuando se usa con el comando [[, esto realiza la coincidencia de patrones como se describió anteriormente (vea Construcciones condicionales ).

'=' debe usarse con el comando de prueba para la conformidad POSIX.

Si desea usar ==, debe usar la [[palabra clave:

$ [[ "a" == "a" ]] && echo yes
yes

Tenga en cuenta que [[es menos portátil (no es POSIX). Pero tanto bash como zsh lo admiten.

zuazo
fuente
1

En ambos shells, bashy zsh, la [utilidad es un shell incorporado. Esta es la implementación de shells de esa herramienta, se usa con preferencia al binario /usr/bin/[. Los diferentes resultados que encuentra son causados ​​por diferentes implementaciones.


En bash, la [utilidad acepta CONDITIONAL EXPRESSIONScomo el [[comando compuesto. De acuerdo a la página hombre bashs tanto =y ==son válidas:

string1 == string2
string1 = string2
        True if the strings are equal.  = should be used with the test command for POSIX
        conformance.

En zsh, la [utilidad intenta implementar POSIX y sus extensiones donde se especifican. En la especificación de la utilidad de prueba POSIX no hay un ==operador definido.

caos
fuente