2

Hi I have a file with the following format:

filename is foo.txt

abcd 1 0 0 2
abef 2 0 0 0
able 2 1 2 0
able 1 0 0 0
efgh 0 0 0 0

I wrote an awk script to delete the row with all columns with 0. But I am getting syntax error. I am sure this is very simple.

Please can anytime help me fix this?

awk 'BEGIN{i=1; While($2==0)($3==0)($4==0) {print $0} }' foo.txt
3

try

awk '$2 != 0 || $3 !=0 || $4 !=0 || $5 !=0 ' foo.txt

where

  • this will filter (grap) line with at least a non zero.
  • please not awk will get line, one by one, no need for while.
  • also original file won't be edited.

Edit:

"the exact opposite" is a bit fuzzy, however to get line with

  • all last field being 0 use $2 == 0 && $3 == 0 && ... (&& stand for logical and to awk, || is logical or)
  • at least a 0 use $2==0 || $3==0 || ...

if you have many fields, to have line with non zero :

awk 'NF>2 {for(i=2;i<=NF;i++) if ($i) {print ; next ;}}' file

where

  • NF is number of field
  • NF>2 ensure line have at least 2 field, and for loop terminate.
  • One thing I noticed was when I said the exact opposite like awk '$2==0 || $3==0 || $4 ==0 ' my file.txt then the output had columns with all zeros as well as columns with 1 values as here: m 0 0 0 /n l 0 0 0 /n i 0 0 0 /n r 0 0 0 /n q 0 0 0 /n p 1 1 0 /n w 0 0 0 /n c 0 0 0 /n F 1 0 1 /n a 0 0 0 /n – genetwister Sep 14 '17 at 20:27
2

Short GNU awk solution (to filter out records with zeros):

awk -v FPAT='[1-9][0-9]*' 'NF' foo.txt

Bonus sed alternative approach:

sed -E '/^[^[:space:]]+ (0[[:space:]]*){4,}$/d' foo.txt

The output (for both approaches):

abcd 1 0 0 2
abef 2 0 0 0
able 2 1 2 0
able 1 0 0 0
0
$ awk '{ c = 0 } { for (i = 2; i <= NF && c == 0; ++i) { c += ($i != 0) } } c > 0' foo.txt
abcd 1 0 0 2
abef 2 0 0 0
able 2 1 2 0
able 1 0 0 0

The script goes through all the fields (skipping the first) and counts how many non-zeroes there are (actually, the counting stops as soon as it finds a non-zero, but that's just a minor optimization). If there were any non-zeroes, the input record is printed.

NF is the number of fields (columns) in the input record (line), and $i references field i. The default action for c > 0, which lacks a { ... } block, is to print the input record.

An equivalent way of writing this script would be

awk '{ c = 0; for (i = 2; i <= NF && c == 0; ++i) { c += ($i != 0) } } c > 0 { print }'

You code has the following issues:

  1. A while statement looks like while (expression) { code } whereas you have while (expression) (expression) ... { code }. This is a syntax error.
  2. The BEGIN block is executed before the first data is read from the file, hence $0, $1 etc. would have no value within it.
0

Simply do:

awk '$2+$3+$4+$5' infile

Or even this one if first column always alphabet:

awk '$0 ~ /[1-9]/' infile
  • That first one is rather neat actually, assuming all numbers are either positive or negative (so that they don't cancel out each other). – Kusalananda Sep 14 '17 at 20:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.