Comparar com eficiência Se a variável existe e não é igual

3

Eu tenho um problema com a sintaxe do script sh . Eu escrevi um script para o meu roteador Asus. O roteiro funciona perfeitamente. Mas eu tenho essa linha:

if [[ "$OldIP" && "$StartIP" != "$OldIP" ]]; then echo OK; fi

Deverá ser verdadeiro (e executar echo OK ) apenas se $StartIP e $OldIP não forem iguais. A linha funciona, mas eu gostaria de ver isso feito de forma mais eficiente. As variáveis contêm endereços IP válidos.

Em alguns casos, $OldIP não será atribuído a nada (não inicializado). Mas, se $OldIP não existir, isso significa que eles não são os mesmos na minha concha!

Eu não quero que a linha faça: se $OldIP não existir - > testar se eles são diferentes - > execute echo OK .

Eu quero que a linha signifique: a) se $OldIP não existir - > fim. mais b) se $OldIP existir - > testar se eles são diferentes - > execute echo OK .

Então, eu gostaria de remover "$OLDIP" && de alguma forma, se possível. Não é um problema real; curioso para aprender:)

Classificar (mas não funciona):

if [ [ "$OldIP" ] != "$StartIP" ]; then echo OK; fi

ou

if [ $OldIP != "$StartIP" ]; then echo OK; fi

que faz o que eu quero, mas reclama quando o OldIP está vazio (mas funciona bem)

enquanto

if [ "$OldIP" != "$StartIP" ]; then echo OK; fi

funciona, mas ignora que OldIP está vazio

    
por Pila 18.05.2016 / 16:56

4 respostas

2

Estritamente falando, uma variável não existe se nunca foi atribuído um valor ou se foi unset . Uma variável com uma string vazia como valor existe .

A expansão de parâmetro padrão ${variable+value} substituirá a seqüência de caracteres value quando variable existir (não está desfeito ou vazio). Isso poderia ser usado para testar a existência assim:

if [ "${OldIP+x}" = "x" ] && [ "$OldIP" != "$StartIP" ]; then
    # code
fi

Para testar se OldIP existe em bash , use o -v test:

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

Isso executaria a comparação de string entre $OldIP e $StartIP apenas se OldIP tivesse sido definido anteriormente (mesmo se estivesse definido como uma string vazia). Note que o teste -v leva o nome da variável.

    
por 01.07.2018 / 08:16
0

Eu acho que seu roteiro é bastante eficiente como é. Você certamente não está gastando muitos ciclos nisso.

Outra maneira de escrever a lógica:

{ test -n "$OldIP" || test "$StartIP" != "$OldIP"; } && echo OK

Isto diz "if OldIP está definido ou se OldIP e StartIP são diferentes, então echo OK.

Lembre-se de que [ é outro nome para test(1) sobre o qual você pode ler com man 1 test .

Edit: Como Gilles apontou, tome cuidado para evitar a criação de subshells ( ... ) onde eles não são necessários.

{ ... ; } pode ser usado para agrupar comandos sem executar um novo shell.

Referência breve: link

    
por 18.05.2016 / 17:15
0

Isso faz o que você pede:

[ "${OldIP:-"$StartIP"}" != "$StartIP" ] && echo "OK"

Como também isso (mais complexo):

${OldIP:+false} || { [[ $OldIP != $StartIP ]] && echo "OK"; }
    
por 19.05.2016 / 11:51
0

Se você estiver usando bash , poderá usar uma substituição padrão:

[[ "${OldIP:=oldunset}" != "${StartIP?StartUnset" ]] && echo "OK"

A sintaxe ${var:-def} será avaliada para o valor atual de $var ou para o padrão especificado (nesse caso, def ) se a variável não estiver definida ou nula. O valor da variável (se houver) não é alterado.

A sintaxe ${var?message} sairá com um código de erro 1, com uma mensagem de message se $var não estiver definida ou nula.

Se você precisar explicitamente de testes compatíveis com test , poderá fazer isso:

[ ! -z "$OldIP" -a "$OldIP" != "$StartIP" ] && echo "OK"
    
por 18.05.2016 / 19:38