21

This is a followup to my earlier question.

I am validating the number of fields in /etc/passwd using this handy snippit. In the following example, the users 'fieldcount1' and 'fieldcount2' have the wrong number of fields:

$ 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

As you'll notice, awk will exit with an return status of 0. From it's standpoint, there are no problems here.

I would like to incorporate this awk statement into a shell script. I would like to print all lines which are error, and set the return code to be 1 (error).

I can try to force a particular exit status, but then awk only prints a single line:

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

Can I force awk to exit with a return status of '1', and print all lines which match?

Stefan Lasiewski
  • 19,264
  • 24
  • 70
  • 85

3 Answers3

29

Keep the status in a variable and use it in an END block.

awk -F: 'NF != 7 {print; err = 1}
         END {exit err}' /etc/passwd
geekosaur
  • 31,429
  • 5
  • 79
  • 58
  • Very good. However I am running into problems incorporating this into a bash script. I am trying to capture the return status of this awk statement by adding something like `; echo $?` after this awk statement. However, `echo $?` is never run because the `END {exit err}'` terminates the script. Is there a way to set the return status without exiting? – Stefan Lasiewski Jul 13 '11 at 17:38
  • 6
    @StefanLasiewski `exit err` terminates awk, it doesn't terminate the script. Do you have `set -e` in that script, by any chance? If so, you've told the shell to exit if a command returns a nonzero status; if you want to test the status, use `if awk …; then echo ok; else echo fail; fi`. – Gilles 'SO- stop being evil' Jul 13 '11 at 22:50
  • @Giles : Yes, this script does have `set -e` set. That explains the strange behavior that I'm seeing. Thanks for pointing that out. – Stefan Lasiewski Jul 13 '11 at 23:21
  • 1
    If you plan to use the output with bash's `&&` operator, it's worth keeping in mind that ["0 is true but false is 1 in the shell"](https://stackoverflow.com/questions/2933843/why-0-is-true-but-false-is-1-in-the-shell). – Skippy le Grand Gourou Oct 31 '19 at 13:37
9

I was looking for something similar to Grep, where it will exit 1 if a match is not found. Here is the equivalent with Awk:

#!/usr/bin/awk -f
BEGIN {
   b1 = 1
}
index($0, "sunday") > 0 {
   b1 = 0
   print
}
END {
   exit b1
}
Zombo
  • 1
  • 5
  • 43
  • 62
0

This does not answer the OP exact requirements, but if you only care about the return code, and not needing to print the lines that match, similar to grep -q, then you can modify @geekasaur answer to exit after the first match, which for huge input files would save time if the error is early in the file. Hopefully /etc/passwd does not qualify for you!

awk -F: 'NF != 7 {err = 1; exit;}
     END {exit err}' /etc/passwd
Mark Stewart
  • 796
  • 1
  • 7
  • 20