Dans un script bash, utilisation du "ou" conditionnel dans une instruction "if"

129

Cette question est une sorte de suite à ma question précédente . Les utilisateurs de ce site m'ont gentiment aidé à déterminer comment écrire une forboucle bash qui itère sur des valeurs de chaîne. Par exemple, supposons qu'une variable de contrôle de boucle effectue une fnameitération sur les chaînes "a.txt" "b.txt" "c.txt". Je voudrais echo"oui!" quand fnamea la valeur "a.txt"ou "c.txt", et echo"non!" autrement. J'ai essayé le script shell bash suivant:

#!/bin/bash

for fname in "a.txt" "b.txt" "c.txt"
do
 echo $fname
 if [ "$fname" = "a.txt" ] | [ "$fname" = "c.txt" ]; then
 echo "yes!"
else
 echo "no!"
fi
done

J'obtiens la sortie:

a.txt

non!

b.txt

non!

c.txt

Oui!

Pourquoi l' ifénoncé semble-t-il être vrai quand fnamea la valeur "a.txt"? Ai-je |mal utilisé ?

Andrew
la source
3
En bash, 'ou' l'opérateur est '||' (Style C).
Marius Cotofana
3
Vous pouvez également utiliser -odans le même [ ].
Thor
6
@Thor Je préfère ||et séparer [ ]plus -opour la portabilité simplement parce que [n'est pas garanti pour soutenir plus de 4 arguments. Bien sûr , si la langue cible est bash, personne ne devrait utiliser de [toute façon , car bash« s [[est supérieure à bien des égards.
jw013
2
@ jw013 Merci. Est-ce que cela signifie que je devrais utiliser if [[ "$fname" = "a.txt" ]] || [[ "$fname" = "c.txt" ]]plutôt que if [ "$fname" = "a.txt" ] || [ "$fname" = "c.txt" ]?
Andrew
5
@ Andrew C'est exact, si vous déclarez le shebang comme bash, comme vous le faites déjà. L’un des avantages de [[ce logiciel est qu’il ne coupe pas les mots (cas particulier) et [[ $unquoted_var = string ]]est donc sûr.
jw013

Réponses:

229

Si vous voulez dire ORutilisez double pipe ( ||).

if [ "$fname" = "a.txt" ] || [ "$fname" = "c.txt" ]

(Le code OP original utilisé |consistait simplement à canaliser la sortie du côté gauche vers le côté droit, de la même manière que tout tuyau ordinaire fonctionne.)

bahamat
la source
4
En outre, ||ne fait pas une logique standard "OU" - il court-circuite, et la deuxième commande est exécutée seulement si la première échoue.
Holdenweb
13
@holdenweb Je suis sûr que la plupart des langages optimisés modernes fonctionnent de la même manière. Inutile de passer des cycles de la CPU pour évaluer la deuxième condition de ORsi la première condition est vraie.
bahamat
1
Je pensais que bash aimait bien ==mais après avoir vu cette réponse, j'ai décidé de chercher. Apparemment, "il peut être utilisé mais n'est pas standard". Je pensais que je mettrais ça ici pour les autres si vous
êtes
C’est ce que testrecommande également la page de
manuel
2
Vous pouvez également utiliser des tests à double crochet - if [[ "$fname" = "a.txt" ]] || [[ "$fname" = "c.txt" ]](si vous souhaitez ou souhaitez que les fonctionnalités supplémentaires soient associées à [[ ]]).
HankCa