awk: форсировать возвращение статуса?

17

Это продолжение моего предыдущего вопроса .

Я проверяю количество полей в / etc / passwd, используя этот удобный фрагмент. В следующем примере пользователи 'fieldcount1' и 'fieldcount2' имеют неправильное количество полей:

$ 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

Как вы заметите, awk выйдет со статусом возврата 0. С этой точки зрения здесь нет проблем.

Я хотел бы включить этот оператор awk в сценарий оболочки. Я хотел бы напечатать все строки, которые являются ошибкой, и установить код возврата равным 1 (ошибка).

Я могу попытаться форсировать определенный статус выхода, но затем awk выводит только одну строку:

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

Могу ли я заставить awk выйти со статусом возврата '1' и распечатать все соответствующие строки?

Стефан Ласевский
источник

Ответы:

23

Сохраните статус в переменной и используйте его в ENDблоке.

awk -F: 'NF != 7 {print; err = 1}
         END {exit err}' /etc/passwd
geekosaur
источник
Очень хорошо. Однако я сталкиваюсь с проблемами, включающими это в сценарий bash. Я пытаюсь зафиксировать возвращаемый статус этого оператора awk, добавив что-то вроде ; echo $?этого оператора awk. Однако echo $?никогда не запускается, потому что END {exit err}'завершает сценарий. Есть ли способ установить статус возврата без выхода?
Стефан Ласевский
6
@StefanLasiewski exit errзавершает awk, но не завершает сценарий. Есть ли у вас set -eв этом сценарии, случайно? Если это так, вы сказали оболочке выйти, если команда возвращает ненулевой статус; если вы хотите проверить статус, используйте if awk …; then echo ok; else echo fail; fi.
Жиль "ТАК - перестань быть злым"
@ Джайлс: Да, этот сценарий set -eустановлен. Это объясняет странное поведение, которое я вижу. Спасибо что подметил это.
Стефан Ласевский
1
Если вы планируете использовать вывод с &&оператором bash , стоит иметь в виду, что «0 истинно, но ложно - 1 в оболочке» .
Скиппи ле Гран Гуру
7

Я искал что-то похожее на grep, где оно будет выходить 1, если совпадение не найдено. Вот эквивалент с awk:

awk '
BEGIN   {z=1}
/bravo/ {z=0; print}
END     {exit z}
' alpha.txt

пример

Стивен Пенни
источник
0

Это не отвечает точным требованиям OP, но если вас заботит только код возврата, и вам не нужно печатать строки, которые совпадают, как grep -q, то вы можете изменить ответ @geekasaur для выхода после первого соответствия, что для огромного ввода файлы сэкономят время, если ошибка возникла в начале файла. Надеюсь /etc/passwd, не подходит для вас!

awk -F: 'NF != 7 {err = 1; exit;}
     END {exit err}' /etc/passwd
Марк Стюарт
источник
1
awk -F: 'NF != 7 {exit 1}'будет делать то же самое.
Стефан