Extract Nth line after matching pattern
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 lnb
th 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 lnb
th 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 lnb
th 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 "--".
Jacob Krieg
Updated on June 06, 2022Comments
-
Jacob Krieg almost 2 years
I want to extract the Nth line after a matching pattern using
grep
,awk
orsed
.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 over 10 years
c&&!--c
is equivalent toc!=0 && --c==0
andc&&c--
is equivalent toc!=0 && --c>=0
; the alternatives may be easier to understand. -
musiphil over 10 yearsOne 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) orawk '/pattern/{p[NR+N]=1} NR in p{print; delete p[NR]}'
(keeps the memory usage bounded). -
Betlista over 7 yearsHow to modify f.) to not to print the line with pattern (it is doing so now)?
-
Betlista over 7 yearsAs answered here - stackoverflow.com/questions/38895234/… the modification is
awk '/abc/ {c=0} c++>4' file
-
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 almost 5 yearsNice work. Also take your time to take the tour to see what Stack Overflow is all about.
-
Admin almost 5 yearsThanks, I will take.