Vérifier si la sortie d'une commande contient une certaine chaîne dans un script shell

116

J'écris un script shell et j'essaie de vérifier si la sortie d'une commande contient une certaine chaîne. Je pense que je dois probablement utiliser grep, mais je ne sais pas comment. Est-ce que quelqu'un sait?

user1118764
la source
La commande doit-elle continuer à s'exécuter après avoir généré la chaîne de sortie que vous recherchez, ou peut-elle être immédiatement fermée à ce moment-là? (Vos deux réponses diffèrent en termes de sémantique à cet égard).
Charles Duffy

Réponses:

97

Testez la valeur de retour de grep:

./somecommand | grep 'string' &> /dev/null
if [ $? == 0 ]; then
   echo "matched"
fi

ce qui se fait de manière idiomatique comme ceci:

if ./somecommand | grep -q 'string'; then
   echo "matched"
fi

et aussi:

./somecommand | grep -q 'string' && echo 'matched'
perréel
la source
2
Ce code ne fonctionne pas avec tous les shells POSIX: le standard POSIX ne nécessite que =d'être un opérateur de comparaison, non ==; voir pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html
Charles Duffy
4
En outre, grep 'string' &>/dev/nullest à la fois non conforme à POSIX et beaucoup plus lent à exécuter (s'il stringapparaît au début d'un long flux de sortie) que grep -q string. [La mise en garde qu'il y a si vous voulez être sûr de somecommandcontinuer à fonctionner même après l'émission string, auquel cas l'utilisation grep -q- en fermant son stdin et en sortant après que la première instance de stringest vue - peut être contre-productive]. (Re: "non-compatible POSIX", &>est une extension - voir pubs.opengroup.org/onlinepubs/009695399/utilities/... décrivant le support de redirection mandaté par POSIX).
Charles Duffy
Cela aiderait s'il était expliqué pourquoi cela fonctionne / ce que fait chaque paramètre, pour encourager une compréhension complète de la syntaxe
redfox05
157

Le test $?est un anti-pattern

if ./somecommand | grep -q 'string'; then
  echo "matched"
fi
tapis
la source
Si, par hasard, vous ne voulez tester qu'une chaîne fixe, ajoutez les options F et x : grep -Fxq F signifie fixed (non interprété) et x pour toute la ligne
Erdal
4
Pourquoi tester l' $?anti-pattern?
Vitaly Zdanevich
1
@VitalyZdanevich Je suppose parce qu'il n'est pas robuste contre la concurrence.
Konrad Reiche
@VitalyZdanevich, pour sa part, testing $?ne définit pas les commandes précédentes comme "vérifiées" pour les besoins de set -eou du ERRpiège, de sorte que votre programme peut quitter dans les cas où vous souhaitez simplement qu'il retourne simplement le chemin intentionnellement faux plus tard. D'autre part, $?c'est un état mondial volatil - il est facile de perdre sa valeur par accident. Par exemple, si vous ajoutez une ligne de journalisation comme echo "Exit status is $?", la nouvelle valeur dans $?devient l'état de sortie de echo.
Charles Duffy
6

Une autre option consiste à vérifier la correspondance des expressions régulières sur la sortie de la commande.

Par exemple:

[[ "$(./somecommand)" =~ "sub string" ]] && echo "Output includes 'sub string'"
Noam Manos
la source
1

Un script shell conditionnel propre if / else:

if ./somecommand | grep -q 'some_string'; then
  echo "exists"
else
  echo "doesn't exist"
fi
Ehsan Barkhordar
la source