Tengo un problema con la sh
sintaxis del script. Escribí un script para mi enrutador Asus. El guión funciona perfectamente. Pero tengo esta línea:
if [[ "$OldIP" && "$StartIP" != "$OldIP" ]]; then echo OK; fi
Debería ser verdadero (y ejecutar echo OK
) sólo si $StartIP
y $OldIP
no son lo mismo. La línea funciona, pero me gustaría que se hiciera de manera más eficiente. Las variables contienen direcciones IP válidas.
En algunos casos, $OldIP
no se le asignará nada (no se inicializará). Pero, si $OldIP
no existe, ¡significa que no son iguales en mi shell!
No quiero que la línea haga: si $OldIP
no existe -> probar si son diferentes -> ejecutar echo OK
.
Quiero que la línea signifique: a) si $OldIP
no existe -> fin. más b) si $OldIP
existe -> probar si son diferentes -> ejecutar echo OK
.
Entonces, me gustaría eliminarlo "$OLDIP" &&
de alguna manera, si es posible. No es un problema real; curiosidad por aprender :)
Algo así (pero no funciona):
if [ [ "$OldIP" ] != "$StartIP" ]; then echo OK; fi
o
if [ $OldIP != "$StartIP" ]; then echo OK; fi
que hace lo que quiero, pero se queja cuandoIP antiguaestá vacío (pero funciona bien)
mientras
if [ "$OldIP" != "$StartIP" ]; then echo OK; fi
funciona pero lo ignoraIP antiguaesta vacio
Respuesta1
Estrictamente hablando, una variable no existe si nunca se le ha asignado un valor, o si se le ha asignado unset
. Una variable con una cadena vacía como valorexiste.
La expansión del parámetro estándar ${variable+value}
sustituirá la cadena value
cuando variable
exista (no esté desarmada ni vacía). Esto podría usarse para probar la existencia de esta manera:
if [ "${OldIP+x}" = "x" ] && [ "$OldIP" != "$StartIP" ]; then
# code
fi
Para probar si OldIP
existe en bash
, use la -v
prueba:
if [[ -v OldIP ]] && [[ "$OldIP" != "$StartIP" ]]; then
# code
fi
Esto realizaría la comparación de cadenas entre $OldIP
y $StartIP
solo si OldIP
se hubiera configurado previamente (incluso si se hubiera configurado en una cadena vacía). Tenga en cuenta que la -v
prueba toma elnombrede la variable.
Respuesta2
Creo que su script es bastante eficiente tal como está. Ciertamente no estás dedicando muchos ciclos a esto.
Otra forma de escribir la lógica:
{ test -n "$OldIP" || test "$StartIP" != "$OldIP"; } && echo OK
Esto dice "si OldIP está configurado o si OldIP y StartIP son diferentes, entonces haga clic en OK.
Recuerda que [
es otro nombre sobre test(1)
el que puedes leer man 1 test
.
Editar: como señaló Gilles, tenga cuidado de evitar crear subcapas ( ... )
donde no sean necesarias.
{ ... ; }
se puede utilizar para agrupar comandos sin ejecutar un nuevo shell.
Breve referencia:http://www.gnu.org/software/bash/manual/html_node/Command-Grouping.html
Respuesta3
Esto hace lo que pides:
[ "${OldIP:-"$StartIP"}" != "$StartIP" ] && echo "OK"
Como también esto (más complejo):
${OldIP:+false} || { [[ $OldIP != $StartIP ]] && echo "OK"; }
Respuesta4
Si está utilizando bash
, puede utilizar una sustitución predeterminada:
[[ "${OldIP:=oldunset}" != "${StartIP?StartUnset" ]] && echo "OK"
La sintaxis ${var:-def}
evaluará el valor actual de $var
o el valor predeterminado especificado (en este caso, def
) si la variable no está configurada o es nula. El valor de la variable (si la hay) no cambia.
La sintaxis ${var?message}
saldrá con un código de error de 1 con un mensaje message
si $var
no está configurado o es nulo.
Si necesita explícitamente test
pruebas compatibles, puede hacer esto:
[ ! -z "$OldIP" -a "$OldIP" != "$StartIP" ] && echo "OK"