0

I have a tab delimited file with four columns. I would like to grep for the lines that have a specific pattern in column 1, where it says apple M of N.  I only want to extract the lines that have the first number matching the second number, or lines that have the first number one less than the second number.  In the example below, rows 2, 3, and 5 (not counting the header row) are the ones that fit the pattern.

Col1                               col2   col3   col4
apple (XY_012345, apple 6 of 10)    1    12228  12612
apple (XY_678901, apple 5 of 6)     1    12722  13220
apple (XY_234567, apple 2 of 2)     1    18437  24737
apple (XY_890123, apple 8 of 30)    1    24892  29269
apple (XY_456789, apple 12 of 12)   1    35175  35276
  • In the example, what pattern do you want to use? – deimos Jun 26 at 15:31
  • I want to extract lines that have "apple N of N", but the two numbers should match, or the second number should be 1 more than the first number. – Sarah Jun 26 at 15:40
  • I updated the title to better reflect your requirements. – Jeff Schaller Jun 26 at 15:47
  • 2
    grep doesn't do math; is some other widely-available UNIX tool acceptable? – Jeff Schaller Jun 26 at 15:48
  • 1
    Yes, it doesn't have to be grep. Sorry, I'm new to this so I wasn't aware that grep couldn't be used. Thanks! – Sarah Jun 26 at 16:21
2

Similar thing in GNU awk:

$ gawk 'match($0, /([0-9]+) of ([0-9]+)/, a) && (a[2] == a[1] || a[2] == a[1]+1)' file
apple (XY_678901, apple 5 of 6)     1    12722  13220
apple (XY_234567, apple 2 of 2)     1    18437  24737
apple (XY_456789, apple 12 of 12)   1    35175  35276
  • I do like the use of the match function though you might want to add NR==1; match... to preserve the first line as well – Valentin Bajrami Jun 26 at 16:05
  • technically, Valentin, the first line doesn't match the criteria, so I guess that would have to be called-for by the OP. – Jeff Schaller Jun 26 at 16:42
2
perl -ne 'print if /(\d+) of (\d+)/ && ($1 == $2 or $1 == ($2 - 1))' < input

This is a "one-liner" perl script that loops over the input you give it and prints lines only if:

  • after matching & capturing two digits separated by the text "of",
  • the first number is equal to the second number or is one less than the second number
  • Alternative shorthand condition ` && ($2 % $1 <2)` – bu5hman Jun 26 at 16:09
  • Thanks, @bu5hman; I've leaned away from golfing to save my future self's sanity -- makes reading the condition vs the logic easier. I don't mind making the computer do another couple operations for that trade-off, but the golfing is fun to see, regardless! – Jeff Schaller Jun 26 at 16:13
  • Fair enough :-D – bu5hman Jun 26 at 16:15
  • Thanks, this works! – Sarah Jun 26 at 16:22

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.