5

I have the following data in a text file:

Name,7/27,7/28,7/29,7/30,7/31,8/1,8/2,8/3,8/4
abc,5,3,8,8,0,0,2,0,11
def,6,7,0,0,0,0,0,2,5
ghi,1,3,5,2,0,0,5,3,6

I need to find out which file (the "Name" column the file name) is giving 5 consecutive 0 as output. In this example, that would be def.

  • 5
    Should a line with six (or more) consecutive zeros be reported? – Kusalananda Aug 10 at 8:17
16

I'd probably do this in awk, using , as a delimiter:

$ awk -F, '/,0,0,0,0,0/{print $1}' file 
def

However, that will also catch a line like this:

mno,6,7,0,0,0,0,0.5

To avoid that, match only if the last 0 is followed by a , or the end of the line:

awk -F, '/,0,0,0,0,0(,|$)/{print $1}' file 
| improve this answer | |
  • This will fail if a line has more than 5 zeros (the question is not clear on what is needed - at least 5 or exactly 5): $ cat ttt Name,7/27,7/28,7/29,7/30,7/31,8/1,8/2,8/3,8/4 abc,5,3,8,8,0,0,2,0,11 def,6,7,0,0,0,0,0,2,5 ghi,1,3,5,2,0,0,5,3,6 jkl,6,7,0,0,0,0,0,0,0,2,5 $ awk -F, '/,0,0,0,0,0(,|$)/{print $1}' ttt def jkl $ – Hopping Bunny Aug 11 at 20:18
  • @HoppingBunny the question asks for "5 consecutive 0". If a line has 45 consecutive zeros, that means it also has five consecutive zeros by definition. Seems perfectly clear to me, I don't know why you would think it should exclude more than 5. Perhaps you meant to comment on the OP instead? – terdon Aug 11 at 21:53
3
grep '0,0,0,0,0' file.txt

prints the matching line: def,6,7,0,0,0,0,0,2,5

grep '0,0,0,0,0' file.txt | cut -d, -f1

prints the first field using , as delimiter: def

| improve this answer | |
  • 4
    This will be fine if the file contains only single-digit numbers - you might want to enforce word boundaries to the pattern like \b0,0,0,0,0\b to prevent matches on sequences like 10,0,0,0,0 – steeldriver Aug 10 at 7:36
  • 4
    @steeldriver, unfortunately \b0,0,0,0,0\b will also match on sequences like 12.0,0,0,0,0.5. – J-L Aug 10 at 19:24
2

using Raku (née Perl6)

Below is an answer that tries to incorporate (and overcome) the objections mentioned by @J-L and @terdon. Also, lines with 5-or-more consecutive zeros are returned. Start first by expanding the test file:

$ cat 5or6_consec_zeros.txt
Name,X,7/27,7/28,7/29,7/30,7/31,8/1,8/2,8/3,8/4
abc,N,5,3,8,8,0,0,0,0,11
def,Y,6,7,0,0,0,0,0,2,5
ghi,N,1,3,5,2,0,0,5,3,6
jkl,N,1,3,5,2,0,0,0,0,0.5
mno,N,7.0,0,0,0,0,2,3,4,5
pqr,Y,1,3,3,0,0,0,0,0,0
stu,Y,1,3,0,0,0,0,0,0,3
vwx,Y,1,3,8,7,0,0,0,0,0

The -ne command line flag tells Raku to run the code line-by-line. The regex tries to match two tokens. In the first token it tries to match exactly 5 repeats of a ",0" two-character sequence. In the second token the regex tries to match either a trailing comma or end-of-line $$ token (after @terdon):

[Note in Raku the | alternation operator implements the longest-token-matching (LTM) strategy. If at some point you need to implement a Perl5-like "first-matching" strategy in Raku, you use Raku's || "first-matching" alternation operator].

$ raku -ne 'when / [\,0]**5 [\,|$$] /  -> { .put };' 5or6_consec_zeros.txt
def,Y,6,7,0,0,0,0,0,2,5
pqr,Y,1,3,3,0,0,0,0,0,0
stu,Y,1,3,0,0,0,0,0,0,3
vwx,Y,1,3,8,7,0,0,0,0,0

To only return the first "column" of (essentially) comma-separated-values, Raku provides an explicit split() method:

$ raku -ne 'when / [\,0]**5 [\,|$$] /  -> { put .split(",")[0] };' 5or6_consec_zeros.txt
def
pqr
stu
vwx

https://raku.org/

| improve this answer | |
  • 1
    I was wondering why you're using '$$' in your regex, as I understand it that would only be useful for multi-line text, and here a '$' works just as well. – Joseph Brenner Aug 16 at 23:34
  • @JosephBrenner admittedly for the code above the end-of-line '$$' zero-width token is overkill. (The traditional end-of-string '$' zero-width token works just as well for the above code). But I prefer to use '$$' whenever I keep whole lines intact, just in case I eventually change the code to read-in multiple line input (or even whole files) all at once. – jubilatious1 Aug 17 at 1:52
1

To get the desired output we may try the below commands.

Gnu sed

$ sed -nE 'G;y/,/\n/;/(\n0){5}\n/P' file

$ awk -F, '/(,0){5}(,|$)/ && $0 =$1""' file

$ grep -oP '^[^,]+(?=.*?(,0){5}(,|$))' file 

Grep with PC Re mode turned on we look for the five consecutive ,0 inside a lookahead so that it doesn't get included un the output bag of grep.

| improve this answer | |
0

Sed can do this:

sed -n '/,0,0,0,0,0[,$]/p' file.txt | sed 's/,.*//'
| improve this answer | |
  • [,$] matches on either the , or $ characters. – Stéphane Chazelas Aug 18 at 19:52
  • You can run more than one sed command in one invocation, no need to run two separate instances piped together. Here sed '/\(,0\)\{5\}\(,.*)\{0,1\}$/!d;s/,.*//' – Stéphane Chazelas Aug 18 at 19:53

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.