2010-11-25 9 views
368

estoy tratando de obtener una declaración if para trabajar en Bash (usando Ubuntu):¿Cómo comparo dos variables de cadena en una instrucción 'if' en Bash?

#!/bin/bash 

s1="hi" 
s2="hi" 

if ["$s1" == "$s2"] 
then 
    echo match 
fi 

He intentado varias formas de la declaración if, utilizando [["$s1" == "$s2"]], con y sin comillas, utilizando =, == y -eq, pero todavía me sale el siguiente error:

[hi: command not found

he mirado en varios sitios y tutoriales y copié los, pero no funciona - ¿qué estoy haciendo mal?

Finalmente, quiero decir si $s1 contiene $s2, entonces ¿cómo puedo hacer eso?

Acabo de resolver los espacios poco ...:/¿Cómo digo que contiene?

me trataron

if [[ "$s1" == "*$s2*" ]] 

pero no funcionó.

+2

La respuesta a su segunda pregunta ('$ s1' contiene' $ s2') está aquí http://stackoverflow.com/questions/229551/string-contains-in-bash – khachik

+0

No, no lo es - Tuve está allí originalmente! –

+0

Oh, lo siento, ya lo veo. Mi error. Disculpas – marcog

Respuesta

497

Para la comparación de cadenas, utilice:

if [ "$s1" == "$s2" ] 

Para el a contiene b, utilice:

if [[ $s1 == *"$s2"* ]] 

(y asegúrese de agregar espacios entre los símbolos):

malo:

if ["$s1" == "$s2"] 

buena:

if [ "$s1" == "$s2" ] 
+17

Por contiene, '[[$ s1 == *" $ s2 "*] ] 'es mejor porque los caracteres especiales (como" * ") en s2 se combinarán literalmente en lugar de comodines. –

+0

@Gordon Editado eso, gracias. – marcog

+3

http://stackoverflow.com/a/229606/376454 Tuve que usar esta respuesta para comparar una variable con una cadena fija. – Wok

128

Se necesitan espacios:

if [ "$s1" == "$s2" ] 
+12

Solo quería decir para asegurarse de dejar un espacio entre los corchetes iniciales y finales y el '" $ s1 "==" $ s2 "' declaración o no funcionará. Además, esto también funciona: 'if test" $ s1 "=" $ s2 "' – racl101

+2

Todo es cuestión de espacio :)) – pooria

+0

este primer comentario de @ racl101 me solucionó el problema. ¡¡Gracias!! –

7

que sugeriría:

#!/bin/bash 

s1="hi" 
s2="hi" 

if [ $s1 = $s2 ] 
then 
    echo match 
fi 

Sin las comillas dobles y con sólo uno es igual.

+0

Sí, es cierto, me perdí los espacios. Con "[$ s1 = $ s2]" funciona. – jzrk

+3

¿Por qué omitirías las comillas dobles? Son opcionales pero inofensivos en este caso específico limitado, pero eliminarlos sería un error grave en muchas situaciones del mundo real. Véase también http://stackoverflow.com/questions/10067266/when-to-wrap-quotes-around-a-variable – tripleee

+0

Pruebe con 's1 = '*'' y 's2 = '*'', y tendrá ver que omitir las comillas dobles es un grave error. –

5

No tengo acceso a un linux box en este momento, pero [es en realidad un programa (y un bash incorporado), así que creo que debe poner un espacio entre [y el primer parámetro.

También tenga en cuenta que el operador de igualdad cadena parece ser una sola =

+0

El símbolo [era un enlace a/bin/prueba al mismo tiempo (o tal vez al revés). Eso aparentemente ya no es el caso en ubuntu 16.04; ni idea de dónde o cuándo ocurrió el cambio. –

1
#!/bin/bash 

s1="hi" 
s2="hi" 

if [ "x$s1" == "x$s2" ] 
then 
    echo match 
fi 

Adición de cadena adicional dentro hace que sea más seguro.

También puede utilizar otra notación para los comandos sola línea:

[ "x$s1" == "x$s2" ] && echo match 
+3

¿Qué significa "más seguro"? Es importante explicar cualquier calificación, en aras de la integridad y la claridad. – mloskot

+3

la verdad es que no es más seguro, ahora sé que sería más seguro si no lo citaras y así evitaría el error de sintaxis si uno de ellos estuviera vacío – mpapis

6
$ if [ "$s1" == "$s2" ]; then echo match; fi 
match 
$ test "s1" = "s2" ;echo match 
match 
$ 
+2

El signo doble igual se tolera en Bash, pero no en otros dialectos. Para la portabilidad, se debe preferir el signo de igual único, y si solo se dirige a Bash, la extensión '[[' de dos corchetes sería superior en cuanto a versatilidad, robustez y conveniencia. – tripleee

102

Usted debe tener cuidado de dejar un espacio entre el signo de '[' y dobles comillas, donde la variable contiene esto:

if [ "$s1" == "$s2" ]; then 
# ^ ^^ ^
    echo match 
fi 

El ^ s muestran los espacios en blanco que necesita para salir.

+2

Muchas gracias por señalar el espacio necesario. Resolvió mi problema Acabo de comenzar bash hoy, parece ser que muchas veces los espacios pueden causar un error, es decir, variables de declaración, etc. –

+0

Punto de bonificación por incluir el '; luego' y 'fi' partes. –

+0

'==' no funciona en ash, dash, u otros lugares implementaciones POSIX de 'prueba'. Use '=' en su lugar. –

1

Para una versión con Bash pura y sin test, pero muy feo, intente:

if (exit "${s1/*$s2*/0}")2>/dev/null 
then 
    echo match 
fi 

Explicación: En () se abre un subnivel adicional. Sale con 0 si hubo una coincidencia e intenta salir con $ s1 si no hubo coincidencia, lo que genera un error (feo). Este error está dirigido a /dev/null.

+0

Nada mal. Me gusta la explicación y la expresión regular sed como. Nunca necesito usar subshell de esa manera. Como sé, puedes obtener la salida con 'command' o $ (command). Estoy seguro de que puedes PRUEBA y luego hacerlo mejor. – erm3nda

+2

Esto se trivializa en caso de que 's2' contenga globs: para solucionarlo, debe citar la expansión' $ s2': '" $ {s1/* "$ s2" */0} "'. Pero hay otros errores sutiles que son imposibles de corregir: por ejemplo, si 's1' es una lista de' 0''s: 's1 = 000000; s2 = some_other_stuff' reclamará una coincidencia. ¡Así que recomendaría altamente no usar este método! Otro error: 's1 = -; s2 = cosas'. A partir de bash 4.4, 's1 = - help; s2 = stuff' también enviaría spam a la salida estándar. –

23

que sugieren éste:

if [ "$a" = "$b" ] 

Aviso el espacio en blanco entre los soportes de Apertura/cierre y las variables y también los espacios blancos que envuelven el signo '='.

Además, tenga cuidado con el encabezado del script. No es lo mismo si se utiliza

#!/bin/bash 

o

#!/bin/sh 

Here's the source.

+0

Votar, pero ten siempre cuidado al leer el ABS. Sería preferible vincularse a una fuente más autorizada. – tripleee

+0

Gracias por el consejo, asegúrese de que una fuente más autorizada sea más precisa. –

+0

/bin/sh: 1: [: falta] – holms

2

¡Esto es más una aclaración que una respuesta! Sí, la clave está en el mensaje de error:

[hi: command not found

que muestra que su "hi" se ha concatenado a la "[".

A diferencia de los lenguajes de programación más tradicionales, en Bash, "[" es un comando como el más obvio "ls" etc. - no se trata especialmente solo porque es un símbolo, por lo tanto, el "[" y el (sustituido) "$ s1" que están inmediatamente uno al lado del otro en su pregunta, se unen (como es correcto para Bash) y luego trata de encontrar un comando en esa posición: [hola - que es desconocido para Bash.

En C y en algunos otros idiomas, el "[" se vería como una "clase de carácter" diferente y sería disjunta del siguiente "hola".

Por lo tanto, necesita un espacio después de la apertura "[".

6

Esta pregunta tiene ya grandes respuestas, pero aquí parece que hay una ligera confusión entre iguales usando iguales y dobles individuales en

if [ "$s1" == "$s2" ] 

La principal diferencia radica en que el lenguaje de secuencias de comandos está usando. Si está utilizando bash, entonces incluya #!/bin/bash en el inicio de la secuencia de comandos y guarde la secuencia de comandos como filename.bash. Para ejecutar use bash filename.bash - entonces tiene que usar ==.

Si está utilizando sh, utilice #!/bin/sh y guarde su secuencia de comandos como filename.sh. Para ejecutar use sh filename.sh - entonces tiene que usar el número =. Evite entremezclarlos.

+1

La afirmación "debe usar' == '" es incorrecta. Bash admite tanto '=' como '=='. Además, si tiene '#!/Bin/bash' al comienzo de su script, puede hacerlo ejecutable y ejecutarlo como'./Filename.bash' (no es que la extensión del archivo sea importante). –

+0

Perfecto, creo que tengo que eliminar esta respuesta ahora, pero será muy útil si explica por qué esto no funciona sin hacer que el archivo sea ejecutable y se ejecute agregando sh/bash antes del nombre del archivo. –

+0

Esto se confunde sobre la importancia del shebang y el nombre del archivo. Si ha colocado correctamente '#!/Bin/sh' o' #!/Bin/bash' como la primera línea del script, simplemente ejecútelo con './Filename' y el nombre real del archivo puede ser completamente arbitrario. – tripleee

Cuestiones relacionadas