Überprüfen, ob die Ausgabe eines Befehls eine bestimmte Zeichenfolge in einem Shell-Skript enthält

115

Ich schreibe ein Shell-Skript und versuche zu überprüfen, ob die Ausgabe eines Befehls eine bestimmte Zeichenfolge enthält. Ich denke, ich muss wahrscheinlich grep verwenden, bin mir aber nicht sicher, wie. Weiß jemand?

user1118764
quelle
Muss der Befehl nach dem Generieren der gewünschten Ausgabezeichenfolge weiter ausgeführt werden oder kann er zu diesem Zeitpunkt sofort geschlossen werden? (Ihre beiden Antworten unterscheiden sich in dieser Hinsicht hinsichtlich ihrer Semantik).
Charles Duffy

Antworten:

97

Testen Sie den Rückgabewert von grep:

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

was idiomatisch so gemacht wird:

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

und auch:

./somecommand | grep -q 'string' && echo 'matched'
perreal
quelle
2
Dieser Code funktioniert nicht mit allen POSIX-Shells: Der POSIX-Standard muss nur =ein Vergleichsoperator sein, nicht ==; siehe pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html
Charles Duffy
4
Auch grep 'string' &>/dev/nullist sowohl nicht-POSIX - kompatibel und wesentlich langsamer ausgeführt werden soll (wenn stringerscheint früh in einem langen Ausgabestrom) als grep -q string. [Die Einschränkung, die es gibt, wenn Sie sicher sein möchten, dass somecommandsie auch nach dem Senden weiterläuft string. In diesem Fall kann die Verwendung grep -q- durch Schließen des Standards und Beenden nach dem ersten Auftreten von - stringkontraproduktiv sein]. (Betreff: "Nicht POSIX-kompatibel" &>ist eine Erweiterung - siehe pubs.opengroup.org/onlinepubs/009695399/utilities/…, in der die von POSIX vorgeschriebene Umleitungsunterstützung beschrieben wird.)
Charles Duffy
Würde helfen, wenn erklärt würde, warum das funktioniert / was jeder Parameter tut, um das vollständige Verständnis der Syntax zu fördern
redfox05
156

Testen $?ist ein Anti-Muster

if ./somecommand | grep -q 'string'; then
  echo "matched"
fi
Matte
quelle
Wenn Sie zufällig nur eine feste Zeichenfolge testen möchten, fügen Sie die Optionen F und x hinzu : grep -Fxq F steht für fest (nicht interpretiert) und x für die gesamte Zeile
Erdal G.
4
Warum ist das Testen von $?Anti-Pattern?
Vitaly Zdanevich
1
@VitalyZdanevich Ich nehme an, weil es nicht robust gegen Parallelität ist.
Konrad Reiche
@VitalyZdanevich Zum einen werden beim Testen $?die vorhergehenden Befehle nicht für die Zwecke set -eoder den ERRTrap als "aktiviert" festgelegt , sodass Ihr Programm in Fällen beendet werden kann, in denen es später einfach den absichtlich falschen Pfad zurückgeben soll. Zum anderen $?ist der globale Staat volatil - es ist leicht, seinen Wert versehentlich wegzuwerfen. Wenn Sie beispielsweise eine Protokollierungszeile wie hinzufügen echo "Exit status is $?", wird der neue Wert in $?zum Exit-Status von echo.
Charles Duffy
6

Eine andere Möglichkeit besteht darin, die Befehlsausgabe auf Übereinstimmung mit regulären Ausdrücken zu überprüfen.

Beispielsweise:

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

Ein sauberes if / else-bedingtes Shell-Skript:

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