web-dev-qa-db-fra.com

Empêcher la sortie de grep en cas de nomatch

Ce script ne fait pas écho "après":

#!/bin/bash -e

echo "before"

echo "anything" | grep e # it would if I searched for 'y' instead

echo "after"
exit

Il en serait de même si je supprimais le -e option sur la ligne Shebang, mais je souhaite la conserver pour que mon script s'arrête en cas d'erreur. Je ne considère pas que grep ne trouve aucune correspondance comme une erreur. Comment puis-je l'empêcher de sortir si brusquement?

33
iago-lito
echo "anything" | grep e || true

Explication:

$ echo "anything" | grep e
### error
$ echo $?
1
$ echo "anything" | grep e || true
### no error
$ echo $?
0
### DopeGhoti's "no-op" version
### (Potentially avoids spawning a process, if `true` is not a builtin):
$ echo "anything" | grep e || :
### no error
$ echo $?
0

Le "||" signifie "ou". Si la première partie de la commande "échoue" (ce qui signifie "grep e" renvoie un code de sortie non nul), la partie après le "||" est exécuté, réussit et renvoie zéro comme code de sortie (true renvoie toujours zéro).

36
John N

Un moyen robuste pour sécuriser et éventuellement grep messages:

echo something | grep e || [[ $? == 1 ]] ## print 'something', $? is 0
echo something | grep x || [[ $? == 1 ]] ## no output, $? is 0
echo something | grep --wrong-arg e || [[ $? == 1 ]] ## stderr output, $? is 1

Selon manuel posix , le code de sortie 1 signifie qu'aucune ligne n'est sélectionnée et> 1 signifie une erreur.

15
James Z.M. Gao

Une autre option consiste à ajouter une autre commande au pipeline - une qui n'échoue pas:

echo "anything" | grep e | cat

Étant donné que cat est désormais la dernière commande du pipeline, c'est l'état de sortie de cat, et non de grep, qui sera utilisé pour déterminer si le pipeline a échoué ou non.

11
roelvanmeer

Solution

#!/bin/bash -e

echo "before"

echo "anything" | grep e || : # it would if I searched for 'y' instead

echo "after"
exit

Explication

set -e ou set -o errexit

Quittez immédiatement si un pipeline (qui peut consister en un seul commande simple), un liste ou un commande composée = (voir Shell GRAMMAR ci-dessus), quitte avec un état différent de zéro. Le shell ne se ferme pas si la commande qui échoue fait partie de la liste de commandes suivant immédiatement un mot clé while ou until, une partie du test suivant le if ou Elif mots réservés, partie de toute commande exécutée dans un && ou || liste sauf la commande suivant la dernière && ou ||, toute commande dans un pipeline sauf la dernière, ou si la valeur de retour de la commande est inversée avec !. Si une commande composée autre qu'un sous-shell renvoie un état différent de zéro car une commande a échoué pendant que -e était ignoré, le shell ne se ferme pas. Une interruption sur ERR, si elle est définie, est exécutée avant la fermeture du shell. Cette option s'applique à l'environnement Shell et à chaque environnement sous-Shell séparément (voir COMMAND EXECUTION ENVIRONMENT ci-dessus) et peut entraîner la fermeture des sous-coquilles avant d'exécuter toutes les commandes de la sous-coquille.

De plus, : est la commande sans effet dans Bash.

5
Cyker

Une autre option:

...
set +e
echo "anything" | grep e
set -e
...
4
Jeff Schaller