¿Cómo comparo cadenas en Bourne Shell?
Pregunta
Necesito comparar cadenas en shell:
var1="mtu eth0"
if [ "$var1" == "mtu *" ]
then
# do something
fi
Pero obviamente el " * " No funciona en Shell. ¿Hay alguna manera de hacerlo?
Solución
bash
Solución más corta:
if [[ "$var1" = "mtu "* ]]
El [[]]
de Bash no se expande globalmente, a diferencia de []
(que debe, por razones históricas).
bash --posix
Oh, publiqué demasiado rápido. Bourne shell, no Bash ...
if [ "${var1:0:4}" == "mtu " ]
$ {var1: 0: 4}
significa los primeros cuatro caracteres de $ var1
.
/bin/sh
Ah, lo siento. La emulación POSIX de Bash no va lo suficientemente lejos; un verdadero Bourne shell original no tiene $ {var1: 0: 4}
. Necesitarás algo como la solución de mstrobl.
if [ "$(echo "$var1" | cut -c0-4)" == "mtu " ]
Otros consejos
Usa las herramientas de Unix. El programa cut
acortará felizmente una cadena.
if [ "$(echo $var1 | cut -c 4)" = "mtu " ];
... deberías hacer lo que quieras.
Puede llamar a expr
para hacer coincidir cadenas con expresiones regulares dentro de los scripts de Bourne Shell. Lo siguiente parece funcionar:
#!/bin/sh
var1="mtu eth0"
if [ "`expr \"$var1\" : \"mtu .*\"`" != "0" ];then
echo "match"
fi
Yo haría lo siguiente:
# Removes anything but first word from "var1"
if [ "${var1%% *}" = "mtu" ] ; then ... fi
O:
# Tries to remove the first word if it is "mtu", checks if we removed anything
if [ "${var1#mtu }" != "$var1" ] ; then ... fi
En el shell Bourne, si quiero verificar si una cadena contiene otra cadena:
if [ `echo ${String} | grep -c ${Substr} ` -eq 1 ] ; then
Adjuntar echo $ {String} | grep -c $ {Substr}
con dos backticks `
:
Para verificar si la subcadena está al principio o al final:
if [ `echo ${String} | grep -c "^${Substr}"` -eq 1 ] ; then
...
if [ `echo ${String} | grep -c "${Substr}<*>quot;` -eq 1 ] ; then
Me gusta usar la declaración de caso para comparar cadenas.
Un ejemplo trivial es
case "$input"
in
"$variable1") echo "matched the first value"
;;
"$variable2") echo "matched the second value"
;;
*[a-z]*) echo "input has letters"
;;
'') echo "input is null!"
;;
*[0-9]*) echo "matched numbers (but I don't have letters, otherwise the letter test would have been hit first!)"
;;
*) echo "Some wacky stuff in the input!"
esac
He hecho locuras como
case "$(cat file)"
in
"$(cat other_file)") echo "file and other_file are the same"
;;
*) echo "file and other_file are different"
esac
Y eso también funciona, con algunas limitaciones, como que los archivos no pueden tener más de un par de megabytes y el shell simplemente no ve nulos, por lo que si un archivo está lleno de nulos y el otro no tiene ninguno, ( y tampoco tienen nada más), esta prueba no verá ninguna diferencia entre los dos.
No uso la comparación de archivos como un ejemplo serio, solo un ejemplo de cómo la declaración de caso es capaz de hacer una coincidencia de cadenas mucho más flexible que la que está disponible con test o expr u otras expresiones de shell similares.
O, como ejemplo del operador = ~ :
if [[ "$var1" =~ "mtu *" ]]