Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get lengths of zeroes (interrupted by ones)

Tags:

bash

awk

I have a long column of ones and zeroes:

0
0
0
1
0
0
0
0
0
1
0
0
0
0
0
1
0
0
1
....

I can easily get the average number of zeroes between ones (just total/ones):

ones=$(grep -c 1 file.txt)
lines=$(wc -l < file.txt)
echo "$lines / $ones" | bc -l

But how can I get the length of strings of zeroes between the ones? In the short example above it would be:

3
5
5
2
like image 923
snd Avatar asked Feb 09 '15 16:02

snd


3 Answers

I'd include uniq for a more easily read approach:

uniq -c file.txt | awk '/ 0$/ {print $1}'
like image 168
erickson Avatar answered Nov 09 '22 06:11

erickson


Edit: fixed for the case where the last line is a 0

Easy in awk:

awk '/1/{print NR-prev-1; prev=NR;}END{if (NR>prev)print NR-prev;}'

Not so difficult in bash, either:

i=0
for x in $(<file.txt); do
  if ((x)); then echo $i; i=0; else ((++i)); fi
done
((i)) && echo $i 
like image 22
rici Avatar answered Nov 09 '22 06:11

rici


Using awk, I would use the fact that a field with the value 0 evaluates as False:

awk '!$1{s++; next} {if (s) print s; s=0} END {if (s) print s}' file

This returns:

3
5
5
2

Also, note the END block to print any "remaining" zeroes appearing after the last 1.

Explanation

  • !$1{s++; next} if the field is not True, that is, if the field is 0, increment the counter. Then, skip to the next line.
  • {if (s) print s; s=0} otherwise, print the value of the counter and reset it, but just if it contains some value (to avoid printing 0 if the file starts with a 1).
  • END {if (s) print s} print the remaining value of the counter after processing the file, but just if it wasn't printed before.
like image 29
fedorqui 'SO stop harming' Avatar answered Nov 09 '22 05:11

fedorqui 'SO stop harming'