`set -e` i idiom` grep` do zapobiegania przedwczesnemu wyjściu ze skryptu powłoki, gdy wzorzec nie został znaleziony

15

Wymagana pomoc - w kontekście skryptów powłoki w bash GNU / LINUX:

Zawsze używam set -e. Często chciałbym grepi nie zawsze chcę, aby skrypt zakończył wykonywanie, jeśli grepma status wyjścia 1wskazujący, że wzorzec nie został znaleziony.

Rozwiązania tego problemu próbowałem rozwiązać w następujący sposób:

(Spróbuj I)
Jeśli set +o pipefaili wywołam grep z czymś takim grep 'p' | wc -l, otrzymam pożądane zachowanie, dopóki przyszły opiekun nie włączy pipefail. Lubię też włączać, pipefailwięc to nie działa dla mnie.

(Wypróbuj II)
Użyj sedlub awki tylko wypisz linie pasujące do wzoru, a następnie wcpasujące linie, aby przetestować pasujący wzór. Nie podoba mi się ta opcja, ponieważ używanie seddo grepwydaje się obejściem mojego prawdziwego problemu.

(Spróbuj III)
Ten jest moim najmniej ulubionym - coś w stylu:set +e; grep 'p'; set-e

Każdy wgląd / idiomy będą mile widziane - dziękuję.

Yeow_Meng
źródło

Odpowiedzi:

19

Możesz ustawić grep w ifstanie, a jeśli nie obchodzi cię status wyjścia, dodaj || true.

Przykład: grepzabija muszlę

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

rozwiązanie 1: wyrzuć niezerowy status wyjścia

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

rozwiązanie 2: jawnie przetestuj status wyjścia

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

Ze strony podręcznika użytkownika bash omawiającej set -e:

Powłoka nie kończy działania, jeśli polecenie, które się nie powiedzie, jest częścią listy poleceń bezpośrednio po słowie kluczowym chwilę lub do , część testu po słowach zastrzeżonych if lub elif , część dowolnego polecenia wykonanego na liście && lub ││, z wyjątkiem polecenie następujące po ostatnim && lub ││ , dowolne polecenie w potoku oprócz ostatniego lub jeśli wartość zwracana polecenia jest odwracana ! .

Glenn Jackman
źródło
Biorąc pod uwagę, że bash przez długi czas nie implementował poprawnie -e, być może dokumentacja nie jest jeszcze poprawna. Ponieważ tekst wydaje się być identyczny ze stroną podręcznika bash-3.x, pamiętaj: wszystkie wersje bash przed wersją bash 4.0 nie zaimplementowały -e niepoprawnie.
schily,
Zauważ też, że ponieważ standard POSIX również był zły, zmieniliśmy tekst POSIX do obsługi błędów za pomocą -e w 2009 r.
schily
1
@schily Podaj wskazówki, gdzie można dowiedzieć się, jakie jest „prawidłowe” zachowanie -e, co bash <4 zrobił inaczej i co zostało zmienione w POSIX.
zwolnienie
Błędy w bash-3 w zasadzie sprawiają, że jest on bezużyteczny, makeponieważ nie zawsze wychodzi z błędów. Jeśli chodzi o powiązane dyskusje na temat POSIX, możesz sprawdzić austingroupbugs.net
schily
@schily Czy mógłbyś być bardziej szczegółowy?
zwolnienie