J'ai un problème avec la sh
syntaxe du script. J'ai écrit un script pour mon routeur Asus. Le script fonctionne parfaitement. Mais j'ai cette ligne:
if [[ "$OldIP" && "$StartIP" != "$OldIP" ]]; then echo OK; fi
Cela ne devrait être vrai (et exécuter echo OK
) que si $StartIP
et $OldIP
ne sont pas identiques. La ligne fonctionne, mais j'aimerais que cela se fasse plus efficacement. Les variables contiennent des adresses IP valides.
Dans certains cas, $OldIP
rien ne sera attribué (n'est pas initialisé). Mais, si $OldIP
n'existe pas, cela signifie qu'ils ne sont pas les mêmes dans ma coquille!
Je ne veux pas que la ligne à faire: si $OldIP
n'existe pas -> tester si elles sont différentes -> exécuter echo OK
.
Je veux que la ligne signifie: a) si $OldIP
n'existe pas -> fin. plus b) s'il $OldIP
existe -> teste si elles sont différentes -> exécutez echo OK
.
Donc, je voudrais supprimer en "$OLDIP" &&
quelque sorte, si possible. Pas un vrai problème curieux d'apprendre :)
En quelque sorte (mais ça ne marche pas):
if [ [ "$OldIP" ] != "$StartIP" ]; then echo OK; fi
ou
if [ $OldIP != "$StartIP" ]; then echo OK; fi
qui fait ce que je veux, mais se plaint quand OldIP est vide (mais fonctionne bien)
tandis que
if [ "$OldIP" != "$StartIP" ]; then echo OK; fi
fonctionne mais ignore que OldIP est vide
Réponses:
Strictement parlant, une variable n’existe pas si elle n’a jamais été affectée à une valeur ou si elle l’a été
unset
. Une variable avec une chaîne vide comme valeur existe .Le paramètre de développement standard
${variable+value}
remplacera la chaînevalue
lorsqu'ellevariable
existe (n'est pas non définie ou vide). Cela pourrait être utilisé pour tester l'existence comme ceci:Pour tester si
OldIP
existe dansbash
, utilisez le-v
test:Ceci effectuerait la comparaison de chaîne entre
$OldIP
et$StartIP
seulement siOldIP
avait déjà été défini (même s'il était défini sur une chaîne vide). Notez que le-v
test prend le nom de la variable.la source
busybox
sh ne supporte pas-v
. Vous pouvez utiliser[ "${OldIP+set}" = set ]
là-bas.bash
. Ma faute. Merci pour la suggestion.Je pense que votre script est assez efficace tel quel. Vous ne passez certainement pas beaucoup de cycles à ce sujet.
Une autre façon d'écrire la logique:
Ceci dit "si OldIP est défini ou si OldIP et StartIP sont différents, alors echo OK.
N'oubliez pas que
[
c'est un autre nom pourtest(1)
lequel vous pouvez lireman 1 test
.Edit: Comme Gilles l’a fait remarquer, veillez à ne pas créer de sous-shell
( ... )
où ils ne sont pas nécessaires.{ ... ; }
peut être utilisé pour regrouper des commandes sans exécuter un nouveau shell.Brève référence: http://www.gnu.org/software/bash/manual/html_node/Command-Grouping.html
la source
{ test … || test …; } && echo OK
ferait la même chose sans créer un sous-shell. Ce ne serait pas une nette amélioration des performances par rapport à l'original (peut-être une légère différence d'une manière ou d'une autre selon le shell0.)Cela fait ce que vous demandez:
Comme aussi ceci (plus complexe):
la source
Si vous utilisez
bash
, vous pouvez utiliser une substitution par défaut:La syntaxe
${var:-def}
sera évaluée à la valeur actuelle de$var
ou à la valeur par défaut spécifiée (dans ce cas,def
) si la variable est non définie ou nulle. La valeur de la variable (s'il y en a une) est inchangée.La syntaxe se
${var?message}
terminera avec un code d'erreur de 1 avec un message demessage
if$var
non défini ou nul.Si vous avez explicitement besoin de
test
tests compatibles, vous pouvez le faire:la source
! -z "STRING"
est identique-n "STRING"
(ou juste"STRING"
)${OldIP:=unset}
échoue la valeur deStartIP
estunset
. Si ce sont des adresses IP comme le nom l'indique, cela ne se produira pas, mais le code sera fragile: que se passera-t-il si le script prend en charge les noms d'hôte un jour?