awk: wymuszanie statusu zwrotu?

18

To kontynuacja mojego wcześniejszego pytania .

Sprawdzam liczbę pól w / etc / passwd za pomocą tego poręcznego snippta. W poniższym przykładzie użytkownicy „fieldcount1” i „fieldcount2” mają niepoprawną liczbę pól:

$ awk -F: ' NF!=7 {print}' /etc/passwd
fieldcount1:x:1000:100:fieldcount1:/home/fieldcount1:/bin/bash::::
fieldcount2:blah::blah:1002:100:fieldcount2:/home/fieldcount2:/bin/bash:
$ echo $?
0

Jak zauważysz, awk zakończy pracę ze statusem zwrotu 0. Z jego punktu widzenia nie ma tu żadnych problemów.

Chciałbym włączyć tę instrukcję awk do skryptu powłoki. Chciałbym wydrukować wszystkie wiersze, które są błędami, i ustawić kod powrotu na 1 (błąd).

Mogę spróbować wymusić określony status wyjścia, ale wtedy awk wypisuje tylko jedną linię:

$ awk -F: ' NF!=7 {print ; exit 1}' /etc/passwd
fieldcount1:x:1000:100:fieldcount1:/home/fieldcount1:/bin/bash::::
$ echo $?
1

Czy mogę zmusić awk do wyjścia ze statusem zwrotu „1” i wydrukować wszystkie pasujące linie?

Stefan Lasiewski
źródło

Odpowiedzi:

23

Zachowaj status w zmiennej i użyj go w ENDbloku.

awk -F: 'NF != 7 {print; err = 1}
         END {exit err}' /etc/passwd
geekozaur
źródło
Bardzo dobre. Mam jednak problemy z włączeniem tego do skryptu bash. Próbuję uchwycić status zwrotu tej instrukcji awk, dodając coś podobnego ; echo $?po tej instrukcji awk. Jednak echo $?nigdy nie jest uruchamiany, ponieważ END {exit err}'kończy skrypt. Czy istnieje sposób ustawienia statusu zwrotu bez wychodzenia?
Stefan Lasiewski
6
@StefanLasiewski exit errkończy awk, nie kończy skryptu. Czy masz przypadkiem set -eten skrypt? Jeśli tak, to powiedziałeś powłoce, aby zakończyła działanie, jeśli polecenie zwróci niezerowy status; jeśli chcesz przetestować status, użyj if awk …; then echo ok; else echo fail; fi.
Gilles „SO- przestań być zły”
@Giles: Tak, ten skrypt jest już set -eustawiony. To wyjaśnia dziwne zachowanie, które widzę. Dzięki za zwrócenie na to uwagi.
Stefan Lasiewski
1
Jeśli planujesz używać danych wyjściowych z &&operatorem bash , warto pamiętać, że „0 to prawda, ale fałsz to 1 w powłoce” .
Skippy le Grand Gourou
8

Szukałem czegoś podobnego do Grepa, gdzie wyjdzie z 1, jeśli nie zostanie znalezione dopasowanie. Oto odpowiednik Awk:

#!/usr/bin/awk -f
BEGIN {
   b1 = 1
}
index($0, "sunday") > 0 {
   b1 = 0
   print
}
END {
   exit b1
}
Steven Penny
źródło
0

To nie odpowiada dokładnym wymaganiom OP, ale jeśli dbasz tylko o kod powrotu i nie musisz drukować pasujących linii, podobnie jak grep -q, możesz zmodyfikować odpowiedź @geekasaur, aby wyjść po pierwszym dopasowaniu, co przy ogromnym wkładzie pliki zaoszczędzą czas, jeśli błąd występuje na początku pliku. Mam nadzieję, /etc/passwdże się nie kwalifikuje!

awk -F: 'NF != 7 {err = 1; exit;}
     END {exit err}' /etc/passwd
Mark Stewart
źródło
1
awk -F: 'NF != 7 {exit 1}'zrobi to samo.
Stéphane Chazelas,