Print line after nth occurrence of a match
Solution 1
awk -v n=3 '/<Car>/ && !--n {getline; print; exit}'
Or:
awk '/<Car>/ && ++n == 3 {getline; print; exit}'
To pass the search pattern as a variable:
var='<car>'
PATTERN="$var" awk -v n=3 '
$0 ~ ENVIRON["PATTERN"] && ++n == 3 {getline; print; exit}'
Here using ENVIRON
instead of -v
as -v
expands backslash-escape sequences and backslashes are often found in regular expressions (so would need to be doubled with -v
).
GNU awk
4.2 or above lets you assign variables as strong typed regexps. As long as its POSIX mode is not enabled (for instance via the $POSIXLY_CORRECT
environment variable, you can do:
# GNU awk 4.2 or above only, when not in POSIX mode
gawk -v n=3 -v pattern="@/$var/" '
$0 ~ pattern && ++n == 3 {getline; print; exit}'
Solution 2
Here's a perl one:
perl -ne 'print && exit if $c==3; $c++ if /<Car>/;' file
With GNU grep
, you can also parse its output like:
grep -A 1 -m 3 '<Car>' file | tail -n 1
From man grep
:
-A NUM, --after-context=NUM
Print NUM lines of trailing context after matching lines.
Places a line containing a group separator (--) between
contiguous groups of matches.
-m NUM, --max-count=NUM
Stop reading a file after NUM matching lines.
Solution 3
With GNU awk
you can do:
gawk -v RS='</Car>' 'NR==3 && $0=$2' inputFile
Solution 4
Here's another way with sed
:
sed -n '/<Car>/{x;/.\{2\}/{x;$!{n;p};q};s/.*/&./;x}' infile
This is using the hold space to count.
Each time it encounters a line matching <Car>
it ex
changes buffers and checks if there are exactly N-1 occurrences of a character in the hold buffer. If the check is successful it ex
changes again, and if not on the last line, it pulls in the n
ext line and p
rints the pattern space then q
uits.
Otherwise it just adds another .
char to the hold space and ex
changes back.
Related videos on Youtube
DJ180
Updated on September 18, 2022Comments
-
DJ180 over 1 year
I am looking to display the line 4598 in the following file. Effectively I want to display the line AFTER the nth occurrence of a match. In this case, the line after the 3rd occurrence of
<Car>
. How do I go about this?<Car> 10456 </Car> <Car> 70192 </Car> <Car> 4598 </Car>
-
devnull about 10 yearsWhile it might be possible to achieve what you want using
sed
,awk
, or evengrep
, it's advisable to make use of a XML parser. -
DJ180 about 10 yearsXML was only used for the example, text may be any format
-
-
rambalachandran almost 8 yearsHow to pass the search pattern also as a variable in the above command
-
Stéphane Chazelas almost 8 years@WanderingMind, see edit.