Reputation: 1142
I have a file that looks like this
3 5 4 0
0 0 0 0
1 3 0 2
What I want is my bash script to only print rows that are not all zeroes. So print out would be
3 5 4 0
1 3 0 2
This is what I have, and it runs with no errors but will not print anything
#!/bin/bash
awk '{total=0; for(i=1;i<NR;i++)$i+=total
if (total!=0) {for(i=1;i<NR;i++) printf("%d ", $i)}}total=0'
Upvotes: 2
Views: 126
Reputation: 41456
Some short awk
:
awk 'NF!=gsub(/0/,"&")' file
3 5 4 0
1 3 0 2
Another one, even shorter:
awk -F"[0 ]*" 'NF>2' file
3 5 4 0
1 3 0 2
Just for fun, some extra:
awk '{a=$0;gsub(/ /,"")} $0+0 {print a}' file
3 5 4 0
1 3 0 2
The regex Ed uses:
awk '/[^0 ]/' file
3 5 4 0
1 3 0 2
And the winner is anubhava
I did a test of the different solution using a large file and time how long it takes. This is the result:
2.071s awk '{k=0; for(i=1; i<=NF; i++) if ($i>0) {k=1;break}} k' large.txt >output
4.284s awk 'NF!=gsub(/0/,"&")' large.txt >output
4.645s awk '{a=$0;gsub(/ /,"")} $0+0 {print a}' large.txt >output
5.103s awk 'NF!=gsub(/0/,"&")' large.txt >output
6.954s grep '[^0 ]' large.txt >output
7.368s awk '/[^0 ]/' large.txt >output
9.374s awk '{s=0;for(i=1;i<=NF;i++)if($i!=0)s=1}s' large.txt >output
12.007s perl -lne '$s=0;map{$s+=$_}$_=~/([0-9]+)/g;print $_ if $s>0;' large.txt >output
25.575s awk -F"[0 ]*" 'NF>2' large.txt >output
Upvotes: 2
Reputation: 77095
Since awk
and other suggestions are already posted, here is way of doing it with perl
:
$ perl -lne '$s=0;map{$s+=$_}$_=~/([0-9]+)/g;print $_ if $s>0;' file
3 5 4 0
1 3 0 2
Upvotes: 0
Reputation: 203324
Your script is printing nothing because total=0
is an assignment whose result is zero which is a false condition. Looks like you're back to confusing NR with NF again too.
Anyway, to do what you now say you want is just:
$ grep '[^0 ]' file
3 5 4 0
1 3 0 2
Upvotes: 2
Reputation: 33317
With awk you can do:
awk '{s=0;for(i=1;i<=NF;i++)if($i!=0)s=1}s' file
Or in a bit more readable format:
#!/usr/bin/awk -f
{
s = 0 # flag is initialized to zero
for (i = 1; i <= NF; i++) # For all fields
if ($i != 0) # If we find a field that is not zero
s = 1 # then set the flag to 1
}
s # Prints the current line (default action) if the flag is
# not zero (and not an empty string)
Upvotes: 2
Reputation: 785058
You can use this egrep:
egrep -v "^(\<0\> *)+$" file
3 5 4 0
1 3 0 2
Using awk:
awk '{k=0; for(i=1; i<=NF; i++) if ($i>0) {k=1;break}} k' file
3 5 4 0
1 3 0 2
Upvotes: 2