Extract Nth line after matching pattern

16,743

Solution 1

To extract the Nth line after a matching pattern you want:

awk 'c&&!--c;/pattern/{c=N}' file

e.g.

awk 'c&&!--c;/Revision:/{c=5}' file

would print the 5th line after the text "Revision:"/.

See Printing with sed or awk a line following a matching pattern for more information.

Solution 2

Printing the lnbth line after first blank/empty line:

Index of line to print (in bash shell):

lnb=2
  • Using sed:

    sed -ne '/^\s*$/{:a;n;0~'"$lnb"'!ba;p;q}' my_file`
    
  • Using perl:

    perl -ne '/^\s+$/ && $k++;$k!=0 && $k++ && $k=='"$lnb"'+2 && (print,last)' my_file`
    

Printing the lnbth line after regular-expression match:

  • Using sed:

    sed -ne '/regex/{:a;n;0~'"$lnb"'!ba;p;q}' my_file
    
  • Using perl:

    perl -ne '/regex/ && $k++;$k!=0 && $k++ && $k=='"$lnb"'+2 && (print,last)' my_file
    

    Bonus 1, Windows PowerShell (install Perl first) :

    $lnb=2
    
    perl -ne "/regex/ && `$k++;`$k!=0 && `$k++ && `$k==$lnb+2 && (print,last)" my_file
    

    Bonus 2, Windows DOS command line :

    set lnb=2
    
    perl -ne "/regex/ && $k++;$k!=0 && $k++ && $k==%lnb%+2 && (print,last)" my_file
    

Printing ALL lnbth lines after regular-expression match:

  • Using perl(bash example):

    perl -ne '/regex/ && $k++;$k!=0 && $k++ && $k=='"$lnb"'+2 && (print,$k=0)' my_file
    

Solution 3

I like solutions I can learn to redo, without having to google for it every time. This solution is not perfect, but uses simple grep commands that I can write from memory.

grep -A7 "searchpattern" file | grep -B1 "^--$" | grep -v "^--$"

You can change the 7 to the nth line you want after the search pattern. It then searches for the "group separator" -- and shows the last line before that. Then remove the group separators.

The only case this does not work correctly is if your data contains lines with only "--".

Share:
16,743
Jacob Krieg
Author by

Jacob Krieg

Updated on June 06, 2022

Comments

  • Jacob Krieg
    Jacob Krieg almost 2 years

    I want to extract the Nth line after a matching pattern using grep, awk or sed.

    For example I have this piece of text:

          Revision:
          60000<br />
    

    And I want to extract 60000.

    I tried Revision:([a-z0-9]*)\s*([0-9]){5} which matches the Revision together with the revision number but when I pass it to grep: grep Revision:([a-z0-9]*)\s*([0-9]){5} file.html I get nothing.

    How can I achieve this?

  • musiphil
    musiphil over 10 years
    c&&!--c is equivalent to c!=0 && --c==0 and c&&c-- is equivalent to c!=0 && --c>=0; the alternatives may be easier to understand.
  • musiphil
    musiphil over 10 years
    One caveat is that if a pattern appears again before reaching the next N'th line, the counter is reset and the earlier appearances are forgotten. For example, in c), if N=10 and the pattern is in lines 21 and 28, then only line 38 will be printed but not line 31. To deal with this, you can use awk '/pattern/{p[NR+N]=1} NR in p' (simpler) or awk '/pattern/{p[NR+N]=1} NR in p{print; delete p[NR]}' (keeps the memory usage bounded).
  • Betlista
    Betlista over 7 years
    How to modify f.) to not to print the line with pattern (it is doing so now)?
  • Betlista
    Betlista over 7 years
    As answered here - stackoverflow.com/questions/38895234/… the modification is awk '/abc/ {c=0} c++>4' file
  • Ed Morton
    Ed Morton over 7 years
    @Betlista No, you just swap the parts that recognize the condition and skip lines to get the rearranged awk '/pattern/{c=N} c&&c--{next} 1' file. What you wrote, awk '/abc/ {c=0} c++>4' file, does something quite different, e.g. it'll unconditionally skip the first 5 lines of input.
  • kvantour
    kvantour almost 5 years
    Nice work. Also take your time to take the tour to see what Stack Overflow is all about.
  • Admin
    Admin almost 5 years
    Thanks, I will take.