Comparar eficientemente si la variable existe y no es igual

Comparar eficientemente si la variable existe y no es igual

Tengo un problema con la shsintaxis 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 $StartIPy $OldIPno 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, $OldIPno se le asignará nada (no se inicializará). Pero, si $OldIPno existe, ¡significa que no son iguales en mi shell!

No quiero que la línea haga: si $OldIPno existe -> probar si son diferentes -> ejecutar echo OK.

Quiero que la línea signifique: a) si $OldIPno existe -> fin. más b) si $OldIPexiste -> 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 valuecuando variableexista (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 OldIPexiste en bash, use la -vprueba:

 if [[ -v OldIP ]] && [[ "$OldIP" != "$StartIP" ]]; then
     # code
 fi

Esto realizaría la comparación de cadenas entre $OldIPy $StartIPsolo si OldIPse hubiera configurado previamente (incluso si se hubiera configurado en una cadena vacía). Tenga en cuenta que la -vprueba 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 $varo 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 messagesi $varno está configurado o es nulo.

Si necesita explícitamente testpruebas compatibles, puede hacer esto:

[ ! -z "$OldIP" -a "$OldIP" != "$StartIP" ] && echo "OK"

información relacionada