`set -e` und` grep`, um zu verhindern, dass das Shell-Skript vorzeitig beendet wird, wenn das Muster nicht gefunden wird

15

Erforderliche Hilfe - im Kontext von Shell-Skripten auf einer GNU / LINUX-Bash:

Ich benutze immer set -e. Oft möchte ich mag grepund nicht immer die Skriptausführung beenden wollen , wenn grepein Exit - Status hat 1angibt Muster nicht gefunden.

Ich habe Folgendes versucht, um dieses Problem zu lösen:

(Versuch ich)
Wenn set +o pipefailund grep mit so etwas aufrufen, grep 'p' | wc -lbekomme ich das gewünschte Verhalten, bis ein zukünftiger Betreuer es ermöglicht pipefail. Außerdem aktiviere ich gerne, pipefailsodass dies bei mir nicht funktioniert.

(Versuchen Sie es mit II)
Verwenden Sie ein sedoder awkund drucken Sie nur Linien, die mit dem Muster wcübereinstimmen, und prüfen Sie dann mit den übereinstimmenden Linien, ob das Muster übereinstimmt. Diese Option gefällt mir nicht, weil die Verwendung von sedto grepals Problemumgehung für mein wahres Problem erscheint.

(Versuchen Sie es mit III)
Dies ist meine am wenigsten beliebte - so etwas wie:set +e; grep 'p'; set-e

Alle Einsichten / Redewendungen wären sehr dankbar - danke.

Yeow_Meng
quelle

Antworten:

18

Sie können das grep in einen ifZustand versetzen oder hinzufügen, wenn Sie sich nicht für den Beendigungsstatus interessieren || true.

Beispiel: greptötet die Shell

$ bash
$ set -e
$ echo $$
33913
$ grep foo /etc/motd
$ echo $$
9233

lösung 1: wirf den nicht-null-ausgangsstatus weg

$ bash
$ set -e
$ echo $$
34074
$ grep foo /etc/motd || true
$ echo $$
34074

Lösung 2: Testen Sie den Exit-Status explizit

$ if ! grep foo /etc/motd; then echo not found; fi
not found
$ echo $$
34074

Auf der bash-Manpage wird Folgendes besprochen set -e:

Die Shell wird nicht beendet, wenn der fehlgeschlagene Befehl Teil der Befehlsliste ist, die unmittelbar auf das Schlüsselwort while oder until folgt , Teil des Tests nach den reservierten Wörtern if oder elif , Teil eines Befehls, der in einer Liste && oder ││ ausgeführt wird, mit Ausnahme von Befehl nach dem letzten && oder ││ , jeder Befehl in einer Pipeline außer dem letzten, oder wenn der Rückgabewert des Befehls mit invertiert wird ! .

Glenn Jackman
quelle
Da die Bash lange Zeit nicht richtig implementiert wurde, kann es sein, dass die Dokumentation noch nicht korrekt ist. Da der Text mit der bash-3.x-Manpage identisch zu sein scheint, beachten Sie bitte, dass alle bash-Versionen vor bash4.0 -e falsch implementiert haben.
Schily
Beachten Sie auch, dass der POSIX-Standard ebenfalls falsch war und wir den POSIX-Text für die Fehlerbehandlung mit -e in 2009
schily
1
@schily Bitte geben Sie Hinweise, wo man herausfinden kann, wie sich -e 'richtig' verhält, was bash <4 anders gemacht hat und was in POSIX geändert wurde.
zwol
Die Bugs in Bash-3 machen es im Grunde unbrauchbar, makeda es nicht immer bei Fehlern beendet wurde. Für die entsprechenden POSIX-Diskussionen können Sie austingroupbugs.net
schily besuchen
@schily Könnten Sie bitte genauer sein?
zwol