Operadores de Igualdad de Bash (==, -eq)

¿Puede alguien explicar la diferencia entre -eq y == en scripts bash?

¿Hay alguna diferencia entre los siguientes?

[ $a -eq $b ] y [ $a == $b ]

¿Es simplemente que == solo se usa cuando las variables contienen números?

Es al revés: == es para las comparaciones de cadenas, -eq es para las numéricas. -eq a la misma familia que -lt , -le , -gt , -ge y -ne , si eso te ayuda a recordar cuál es cuál.

 $ [ a == a ]; echo $? 0 $ [ a -eq a ]; echo $? -bash: [: a: integer expression expected 2 

== es un bash-ismo El formulario POSIX es = . Si la portabilidad a las conchas que no son bash es importante, use = .

== es un alias específico de bash para = y realiza una comparación de cadena (léxico) en lugar de una comparación numérica. eq es una comparación numérica del curso.

Finalmente, generalmente prefiero usar el formulario if [ "$a" == "$b" ]

Depende de la construcción de prueba alrededor del operador. Sus opciones son doble paréntesis, llaves dobles, llaves individuales o prueba

Si usa ((…)) , está probando la equidad aritmética con == como en C:

 $ (( 1==1 )); echo $? 0 $ (( 1==2 )); echo $? 1 

(Nota: 0 significa true en el sentido de Unix y no cero es una prueba fallida)

Usar -eq dentro del doble paréntesis es un error de syntax.

Si está utilizando […] (o un solo corsé) o [[]] (o doble corsé), o test , puede usar uno de los siguientes: -eq, -ne, -lt, -le, -gt, o -ge como una comparación aritmética .

 $ [ 1 -eq 1 ]; echo $? 0 $ [ 1 -eq 2 ]; echo $? 1 $ test 1 -eq 1; echo $? 0 

El == dentro de llaves simples o dobles (o comando de test ) es uno de los operadores de comparación de cuerdas :

 $ [[ "abc" == "abc" ]]; echo $? 0 $ [[ "abc" == "ABC" ]]; echo $? 1 

Como operador de cadena, = es equivalente a == y observe el espacio en blanco alrededor = o == es requerido.

Si bien puede hacer [[ 1 == 1 ]] o [[ $(( 1+1 )) == 2 ]] está probando la igualdad de la cadena, no la igualdad aritmética.

Entonces -eq produce el resultado probablemente esperado que el valor entero de 1+1 sea ​​igual a 2 aunque la RH sea una cadena y tenga un espacio final:

 $ [[ $(( 1+1 )) -eq "2 " ]]; echo $? 0 

Mientras que una comparación de cadenas de las mismas recoge el espacio final y, por lo tanto, la comparación de cadenas falla:

 $ [[ $(( 1+1 )) == "2 " ]]; echo $? 1 

Y una comparación errónea de cadenas puede producir la respuesta incorrecta completa. ’10’ es lexicográficamente menor que ‘2’, por lo que una comparación de cadenas devuelve true o 0 . Muchos son mordidos por este error:

 $ [[ 10 < 2 ]]; echo $? 0 

vs la prueba correcta para 10 siendo aritméticamente menos de 2:

 $ [[ 10 -lt 2 ]]; echo $? 1 

En los comentarios, hay una cuestión de la razón técnica que usa el integer -eq en cadenas devuelve True para cadenas que no son las mismas:

 $ [[ "yes" -eq "no" ]]; echo $? 0 

La razón es que Bash está sin tipo . El -eq hace que las cadenas se interpreten como enteros si es posible, incluida la conversión base:

 $ [[ "0x10" -eq 16 ]]; echo $? 0 $ [[ "010" -eq 8 ]]; echo $? 0 $ [[ "100" -eq 100 ]]; echo $? 0 

Y 0 si Bash piensa que es solo una cadena:

 $ [[ "yes" -eq 0 ]]; echo $? 0 $ [[ "yes" -eq 1 ]]; echo $? 1 

Entonces [[ "yes" -eq "no" ]] es equivalente a [[ 0 -eq 0 ]]

Última nota: muchas de las extensiones específicas de Bash para los constructos de prueba no son POSIX y, por lo tanto, fallarán en otros shells. Otros shells generalmente no son compatibles con [[...]] y ((...)) o == .

Chicos: Varias respuestas muestran ejemplos peligrosos. El ejemplo de OP [ $a == $b ] utilizó específicamente la sustitución de variables sin comillas (a partir de octubre de 17 edición). Porque [...] eso es seguro para la igualdad de cuerdas.

Pero si va a enumerar alternativas como [[...]] , debe informar también que se debe citar el lado derecho. Si no se cita, ¡es una coincidencia de patrón! (Desde la página bash man: “Se puede citar cualquier parte del patrón para forzarlo a coincidir como una cadena”).

Aquí en bash, las dos afirmaciones que dan “sí” son coincidencia de patrones, otras tres son igualdad de cadenas:

 $ rht="A*" $ lft="AB" $ [ $lft = $rht ] && echo yes $ [ $lft == $rht ] && echo yes $ [[ $lft = $rht ]] && echo yes yes $ [[ $lft == $rht ]] && echo yes yes $ [[ $lft == "$rht" ]] && echo yes $