Il semble que ce soit un bug dans votre code, mais nous pouvons le refactoriser vraiment petit...
Si vous aviez vraiment écrit votre expression avec [ foo = bar -o foo = car -o foo = jar -o foo = foo ]
, alors cela aurait pu être simplifié à :
echo oui
Cette condition est toujours vraie car foo = foo
est toujours vrai, ce qui est lui-même vrai car la chaîne littérale foo
est toujours la même que lui-même.
Bien que vous ayez clarifié que cette syntaxe n'apparaissait pas dans le code que vous utilisiez vraiment, j'ai gardé cette section d'introduction car c'est une erreur courante de le faire, surtout parmi les novices. Essayer de vérifier la valeur de foo
de cette manière ne fonctionne pas dans un shell de style Bourne--pour examiner la valeur d'une variable avec [
, vous devez effectuer une expansion de paramètres avec $
(voir ci-dessous). Cet aspect particulier du problème n'est pas spécifique à un shell ; par exemple, voici un test dans 7 shells de style Bourne.
Réparation du Code Initial
Peut-être vouliez-vous vérifier la valeur de la variable foo
(c'est-à-dire son contenu, plutôt que son nom) contre ces chaînes. Dans ce cas, votre code initial ressemblerait à ceci :
if [ "$foo" = bar -o "$foo" = car -o "$foo" = jar -o "$foo" = foo ]; then
echo oui
fi
Cela peut être légèrement raccourci avec l'opérateur de court-circuit &&
:
[ "$foo" = bar -o "$foo" = car -o "$foo" = jar -o "$foo" = foo ] && echo oui
Mais c'est toujours plus long, plus compliqué et plus répétitif que ce que vous préférez probablement. Donc, passons à autre chose...
Formes Plus Courtes via Correspondance de Motifs
Vous pouvez utiliser l'opérateur de correspondance de motif intégré de la facilité [[
:
[[ $foo =~ ^(bar|car|jar|foo)$ ]] && echo oui
Alors que l'utilisation de case
est probablement la manière la plus courante, l'utilisation de [[
avec =~
est :
- de même longueur qu'une utilisation compacte de
case
(voir ci-dessous)
- probablement plus fidèle à la logique de votre code initial, dans la mesure où il utilise
[[
, qui fonctionne comme une expression de test.
Vous pourriez donc préférer cela. C'est la méthode que j'utiliserais probablement pour faire cela en bash.
Si vous vouliez faire quelque chose de similaire mais en utilisant grep
au lieu de [[
avec =~
, voici une méthode similaire :
grep -Eq '^(bar|car|jar|foo)$' <<< "$foo" && echo oui
Ou cela :
grep -Fqe{bar,car,jar,foo} <<< "$foo" && echo oui
Un One-Liner avec case
Comme le dit Serg, cela peut être simplifié en utilisant case
au lieu de if
et [
. C'est la manière classique et probablement la plus courante.
La méthode dans la réponse de Serg fonctionne parfaitement bien, mais pour le code particulier que vous refactorez, nous pouvons écrire quelque chose de plus simple, en n'utilisant qu'un seul motif pour case
. Il n'est pas nécessaire d'avoir une correspondance *)
par défaut à la fin. Si la chaîne ne correspond à aucun des motifs, le contrôle passe simplement à travers la construction case
et aucune commande n'est exécutée, ce qui est équivalent à votre construction if
sans else
.
case $foo in bar|car|jar|foo) echo oui;; esac
Cela le rend assez court et simple pour tenir facilement--et être lisible--sur une seule ligne (ce qui semble être ce que vous recherchez). Cette méthode est également portable à des shells de style Bourne autres que bash.