23

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,754
  • 24
  • 70
  • 85

3 Answers3

30

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
  • 32,047
  • 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". – 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
  • 44
  • 63
1

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