Ils semblent tous les deux indiquer à BASH de commencer par une autre commande suivant les symboles, mais existe-t-il une différence nette?
Ils semblent tous les deux indiquer à BASH de commencer par une autre commande suivant les symboles, mais existe-t-il une différence nette?
Réponses:
Avec cette ligne:
command1 && command2
commande2 sera exécutée si (et seulement si) commande1 renvoie le statut de sortie zéro, alors que dans cette ligne:
command1 ; command2
commande1 et commande2 seront exécutés indépendamment. Le point-virgule vous permet de saisir plusieurs commandes sur une seule ligne.
Vous pouvez essayer la différence par vous-même:
ls /invalid/path && echo "hello!"
Puisque / invalid / path n'existe pas, ls ne peut pas vous montrer la liste des répertoires. Il échouera avec un message d'erreur: "ls: / invalid / path: Aucun fichier ou répertoire de ce type".
La seconde moitié de la commande (echo "hello!") N'est jamais exécutée car la première moitié a échoué.
ls /invalid/path ; echo "hello!"
Le même message d'erreur apparaît comme avant, mais cette fois, la deuxième partie est exécutée !
ls: / invalid / path: Aucun fichier ou répertoire de ce type
hello!
Pourquoi est-ce utile?
Supposons que vous souhaitiez extraire un fichier appelé archive.tar.gz.
Vous pouvez utiliser la commande tar zxvf archive.tar.gz && rm archive.tar.gz
.
Si pour une raison quelconque l'extraction de l'archive échoue, la deuxième partie n'est pas exécutée! Vous pouvez réessayer.
Si tu utilises ; dans la même situation, l'archive est supprimée et vous ne pouvez plus essayer.
&&
is AND
, ce qui signifie que la deuxième commande ne sera exécutée que si la première a renvoyé la valeur true (aucune erreur).
AND
exécution, le deuxième paramètre devient inutile si le premier est égal à: false
le code sous-jacent est donc optimisé pour différer l'évaluation du deuxième paramètre jusqu'à ce qu'il sache en quoi consiste le premier.
&&
est juste un opérateur binaire, une fonction. La seule chose "spéciale" est qu’il s’agit de la notation infixe (qui est de toute façon la norme pour la plupart de ces types d’opérateurs) et de l’exécution tardive du second opérande. Cette exécution retardée lui donne en effet la possibilité d’être utilisée de manière conceptuelle comme une if
instruction dans ce contexte , mais cela n'enlève rien au fait que l’utilisation initialement prévue est dans les conditions d’une if
instruction réelle . L'utilisation ici est vraiment plus d'un "hack".
a && b || c = (a && b) || c
. Ordre d'évaluation simple. Il n'y a vraiment pas de mystère là-bas. Si vous les écrivez comme vos fonctions typiques, cela ressemblerait simplement à or(and(a, b), c)
. Cette logique est la même dans un if
conditionnel et lors de son entrée directe dans la ligne de commande car &&
et ||
sont des opérateurs , ils prennent deux opérandes et en retournent un autre.
Mise à jour : j'ai ajouté comme script pour mettre en évidence certains des pièges possibles:
Parce que personne n'a mentionné "||", je vais
Update2 : une reformulation importante ici
&& est comme un "alors" d'une instruction "if" qui répond à "true"
|| n'est pas comme le "else" d'une déclaration "if" ..
|| est comme un "alors" d'une "si" déclaration qui répond à "faux"
Plus précisément, && teste le $? renvoie la valeur de la dernière instruction exécutée précédemment et passe le contrôle à l'instruction ou au sous-shell immédiatement après le && ... il ne transmet le contrôle que si $? est vrai.
|| est similaire et est souvent vu après une instruction &&, mais il teste une valeur de retour fausse ($?) à partir de la dernière instruction exécutée précédemment ... NB! Nota Bene! Notez bien! .... si l'instruction prédecing est une instruction && qui renvoie faux lorsque vous vous attendez à ce qu'elle soit vraie, alors || répondra au faux, donc mélanger les deux sur la même ligne peut être risqué
Le point principal que j'essaie de faire valoir concerne une erreur que j'ai commise. c'est-à-dire:
## [[condition]] && A || B
n'est pas ne se comporte pas comme un ternaire de style C / C ++. c'est-à-dire:
// (condition)? A: B
Voir le script ci-dessous pour des exemples de résultats "inattendus" de "A"
Le test de base et le && et le || déclaration doit tous être sur la même ligne ...
Exécutez ce script pour voir où les problèmes peuvent survenir avec && et ||
La dernière déclaration exécutée peut ne pas être celle que vous attendez.
[[condition]] && echo Hello || echo Au revoir .... est généralement sans danger,
car un écho bien formé retournera vrai.
mais qu'en est-il de l'accès à un fichier qui n'existe pas?
#!/bin/bash
#
# "as expected" return codes" means: expected to behave like a normal AND / OR contition test
#
if [[ "$1" != "" ]] ; then exit $1; fi # recursive call to return an arbitary $? value (decimal)
echo
echo 'test 1: All return codes are "as expected"'
echo ======
((1==1)) && echo " ((1==1)) rc=$? ..&&.. condition is true" || echo " ((1==1)) rc=$? ..||.. condition is false"
$0 0 && echo " \$0 0 rc=$? ..&&.. condition is true" || echo " \$0 0 rc=$? ..||.. condition is false"
((1!=1)) && echo " ((1!=1)) rc=$? ..&&.. condition is true" || echo " ((1!=1)) rc=$? ..||.. condition is false"
$0 1 && echo " \$0 1 rc=$? ..&&.. condition is true" || echo " \$0 1 rc=$? ..||.. condition is false"
echo
echo 'test 2: Now throw in some "unexpected" errors into the first of the &&/|| pair'
echo ======
((1==1)) && (echo " ((1==1)) rc=$? ..&&.. condition is true"; $0 1) || echo " ((1==1)) rc=$? ..||.. condition is false"
$0 0 && (echo " \$0 0 rc=$? ..&&.. condition is true"; $0 2) || echo " \$0 0 rc=$? ..||.. condition is false"
((1!=1)) && (echo " ((1!=1)) rc=$? ..&&.. condition is true"; $0 3) || echo " ((1!=1)) rc=$? ..||.. condition is false"
$0 1 && (echo " \$0 1 rc=$? ..&&.. condition is true"; $0 4) || echo " \$0 1 rc=$? ..||.. condition is false"
echo
echo 'test 3: Now swap the order of && and || statements, using "as expected" return codes'
echo ======
((1==1)) || echo " ((1==1)) rc=$? ..||.. condition is true" && echo " ((1==1)) rc=$? ..&&.. condition is false"
$0 0 || echo " \$0 0 rc=$? ..||.. condition is true" && echo " \$0 0 rc=$? ..&&.. condition is false"
((1!=1)) || echo " ((1!=1)) rc=$? ..||.. condition is true" && echo " ((1!=1)) rc=$? ..&&.. condition is false"
$0 1 || echo " \$0 1 rc=$? ..||.. condition is true" && echo " \$0 1 rc=$? ..&&.. condition is false"
echo
echo 'test 4: With the order of && and || statements still swapped, introduce "unexpected" errors into the first of the &&/|| pair'
echo ======
((1==1)) && (echo " ((1==1)) rc=$? ..&&.. condition is true"; $0 1) || echo " ((1==1)) rc=$? ..||.. condition is false"
$0 0 && (echo " \$0 0 rc=$? ..&&.. condition is true"; $0 2) || echo " \$0 0 rc=$? ..||.. condition is false"
((1!=1)) && (echo " ((1!=1)) rc=$? ..&&.. condition is true"; $0 3) || echo " ((1!=1)) rc=$? ..||.. condition is false"
$0 1 && (echo " \$0 1 rc=$? ..&&.. condition is true"; $0 4) || echo " \$0 1 rc=$? ..||.. condition is false"
exit
essayer
false && echo "bonjour"
et
faux ; echo "bonjour"
regarde la différence
La commande (fonction, dans le cas d’un script) après &&
est exécutée en fonction du RETVAL de la première commande (fonction, dans le cas d’un script). Cela force la première commande à renvoyer la valeur 0 si elle aboutit. Nous pouvons vérifier la valeur de retour pour exécuter d'autres commandes.