Comparar cadenas en Shell Script
Una de las tareas más habituales a la hora de programar es comparar cadenas, si dos cadenas son iguales, si no son iguales, si una contiene a otra… todo esto y más podemos hacer en Shell Script.
Para empezar, vamos a comprobar si una cadena está vacía o no.
-z
devuelve verdadero si la cadena está vacía (tiene longitud 0).
-n
devuelve verdadero si la cadena no está vacía (su tamaño es mayor que 0).
#!/bin/bash string="" string2="Hola, mundo" if [ -z "$string" ] then echo La cadena está vacía fi if [ -n "$string2" ] then echo La cadena no está vacía: $string2 fi
Que nos devuelve:
La cadena está vacía La cadena no está vacía: Hola, mundo
Otra forma de comprobar si la cadena tiene algo sería comprobar si el tamaño de la cadena es mayor que 0:
#!/bin/bash string="" string2="Hola, mundo" if [ "${#string}" -gt 0 ] then echo La cadena \$string contiene más de cero caracteres. fi if [ "${#string2}" -gt 0 ] then echo La cadena \$string2 contiene más de cero caracteres. fi
Que devuelve:
La cadena $string2 contiene más de cero caracteres.
Para comparar si dos cadenas coinciden podemos usar el estándar POSIX [], equivalente al comando test y más compatible con cualquier lenguaje de scripts POSIX o podemos usar el bashismo [[ ]].
En teoría, la primera opción comprobaremos la igualdad con un único igual (=), mientras que en la segunda opción compararemos con doble igual (==):
#!/bin/bash name="fernando" if [ $USER = "$name" ] then echo El usuario $USER coincide con el nombre $name comparando con test. fi if [[ $USER == "$name" ]] then echo El usuario $USER coincide con el nombre $name comparado con el bashismo [[ ]]. fi
que, en mi caso, que mi usuario se llama fernando, me devuelve:
El usuario fernando coincide con el nombre fernando comparando con test. El usuario fernando coincide con el nombre fernando comparado con el bashismo [[ ]].
Antes he escrito que, en teoría con corchete se compara con un igual y con doble corchete se compara con doble igual, pero en las versiones modernas de Bash, se pueden usar indistintamente = y ==:
#!/bin/bash name="fernando" if [ $USER == "$name" ] then echo El usuario $USER coincide con el nombre $name comparando con test. fi if [[ $USER = "$name" ]] then echo El usuario $USER coincide con el nombre $name comparado con el bashismo [[ ]]. fi
También me devuelve:
El usuario fernando coincide con el nombre fernando comparando con test. El usuario fernando coincide con el nombre fernando comparado con el bashismo [[ ]].
Aunque, si queremos ser más compatibles con todos los sistemas y todas las versiones, mejor usar [ $USER = "$name" ]
Para comprobar la desigualdad, lo haremos en ambos casos con !=:
#!/bin/bash name="pepe" if [ $USER != "$name" ] then echo El usuario $USER no coincide con el nombre $name comparando con test. fi if [[ $USER != "$name" ]] then echo El usuario $USER no coincide con el nombre $name comparado con el bashismo [[ ]]. fi
Que devuelve:
El usuario fernando no coincide con el nombre pepe comparando con test. El usuario fernando no coincide con el nombre pepe comparado con el bashismo [[ ]].
Por último vamos a ver cómo comprobar si una cadena contiene una subcadena. Esto lo haremos con [[ "$cadena" =~ "$subcadena" ]]
. Vamos a ver las dos maneras, para que una devuelva error, y así aprendemos del fallo, y otra lo haga bien, y así aprendemos cómo hacerlo:
#!/bin/bash name="fer" if [ $USER =~ "$name" ] then echo El usuario $USER contiene la subcadena $name comparando con test. fi if [[ $USER =~ "$name" ]] then echo El usuario $USER contiene la subcadena $name comparado con el bashismo [[ ]]. fi
Que devuelve:
línea 6: [: =~: se esperaba un operador binario El usuario fernando contiene la subcadena fer comparado con el bashismo [[ ]].
Por lo que vemos que para comprobar si una cadena contiene una subcadena, tenemos que usar la opción moderna de Bash.