Display only the n'th match of grep

77,918

Solution 1

try this:

awk '/two/{i++}i==2' file

with your data:

kent$  echo "onefish
onechicken
twofish
twochicken
twocows
threechicken"|awk '/two/{i++}i==2'
twochicken

note: if your file is huge, do this:

awk '/two/{i++}i==2{print; exit}' file

Solution 2

grep -m2 "two" in-file.txt | tail -n1

Stop after the second match, then take the second line printed.

Solution 3

grep and sed can be used to filter the line number.

testfile:

onefish
onechicken
twofish
twochicken
threechicken
twocows

Getting the desired line:

grep "two" testfile | sed -n 2p
prints "twochicken"

grep "two" testfile | sed -n 1p
prints "twofish"

Solution 4

If the word (here word==two) repeats multiple time in a single line, & you want to print that line, use below:

word=two
n=2
line=`grep -m$n $word -o -n MyFile | sed -n $n's/:.*//p'`
awk 'FNR=='$line'{print; exit}' MyFile 

e.g. For below input:

onefish
onechicken
twotwofish
twochicken
twocows
threechicken

it will print twotwofish, instead of twochicken.

This may not be what user1787038 wants, but added to answer my own comment.

Solution 5

It should be noted that if the threechicken and twocows lines were swapped, aka:

onefish
onechicken
twofish
twochicken
threechicken
twocows

then Kent's first response (awk '/two/{i++}i==2' file) would yield the output:

twochicken
threechicken

because it takes another occurrence of the match to increment the counter. His last response: awk '/two/{i++}i==2{print; exit}' file avoids this issue.

Share:
77,918
Andrew Tsay
Author by

Andrew Tsay

Updated on July 09, 2022

Comments

  • Andrew Tsay
    Andrew Tsay almost 2 years
    onefish
    onechicken
    twofish
    twochicken
    twocows
    threechicken
    

    What if I want to grep for lines containing "two", but I only want the 2nd match. So I want the result "twochicken".

  • poncha
    poncha about 11 years
    the second option is superior regardless of filesize, no ?
  • poncha
    poncha about 11 years
    that does not exactly do what is expected. if there are more matches than two, it will output multiple lines...
  • poncha
    poncha about 11 years
    what do you mean by 'line number' ? i meant that adding {print; exit} would be good idea for any input size... oh. that was option #3 actually ;) i counted wrong)))
  • Thor
    Thor about 11 years
    The tail should be: tail -n1.
  • John Zwinck
    John Zwinck about 11 years
    @poncha: really? The grep -m2 makes sure there are only two matches. I changed it anyway, though I think it was OK before.
  • anishsane
    anishsane about 11 years
    is there a way to stop at nth occurrence of the word? I mean, if the "word" is repeated multiple times in a single line?
  • anishsane
    anishsane about 11 years
    -m$n in grep line is just for some optimization, not needed for functionality.
  • Kent
    Kent about 11 years
    @anishsane i think there is.
  • rambalachandran
    rambalachandran almost 8 years
    Is there a way to pass a the search-pattern and the no. of occurence N as a string
  • Kent
    Kent almost 8 years
    @WanderingMind yes, you can define variables
  • rambalachandran
    rambalachandran almost 8 years
    Can you edit your answer to let me know how to pass a variable as search pattern
  • Kent
    Kent almost 8 years
    awk -v p="two" -v n="2" '$0~p{i++}i==n' file @WanderingMind
  • rambalachandran
    rambalachandran almost 8 years
    Thank you for the reply.
  • DreadPirateShawn
    DreadPirateShawn over 6 years
    This is buggy -- if you remove twocows from the example, then it prints both twocows and threechickens, because i only iterates on lines that include "two" -- so if i reaches 2 on the last occurrence of the target string, then i remains 2 throughout the rest of the file, and every subsequent line is printed. (However, the "if your file is huge" addendum fixes this bug.)
  • Manuel Jordan
    Manuel Jordan over 2 years
    @Kent can you please explain what does {i++}i==2 do?
  • Kent
    Kent over 2 years
    @ManuelJordan /two/{A} i==2 {B} = if($0~/two) do A; if(i==2) do B