I am trying to print the matched line and the 4th line from the matched line (line containing the expression I am searching for).
I have been using the following code:
sed -n 's/^[ t]*//; /img class="devil_icon/,4p' input.txt
But this only prints the matched line.
This prints only the 4th line.
awk 'c&&!--c;/img class="devil_icon/{c=4}' input.txt
I need to print both the matched line and the 4th line only.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
In awk, you’d do it as follows
awk '/pattern/{nr[NR]; nr[NR+4]}; NR in nr' file > new_file`
or
awk '/pattern/{print; nr[NR+4]; next}; NR in nr' file > new_file`
Explanation
The first solution finds all lines that match pattern
. When it finds a match it stores the record number (NR
) in the array nr
. It also stores the 4th record from NR
in the same array. This is done by the nr[NR+4]
. Every record (NR
) is then checked to see if it’s present in the nr
array, if so the record is printed.
The second solution works essentially the same way, except when it encounters th e pattern
it prints that line, and then stores the 4th record ahead of it in the array nr
, then goes to the next record. Then when awk
encounters this 4th record the NR in nr
block will get executed and print this +4 record there after.
Example
Here’s an example data file, sample.txt
.
$ cat sample.txt 1 2 3 4 blah 5 6 7 8 9 10 blah 11 12 13 14 15 16
Using the 1st solution:
$ awk '/blah/{nr[NR]; nr[NR+4]}; NR in nr' sample.txt 4 blah 8 10 blah 14
Using the 2nd solution:
$ awk '/blah/{print; nr[NR+4]; next}; NR in nr' sample.txt 4 blah 8 10 blah 14
Method 2
You can try the -A
option with grep
, which specifies how many lines after the matching line should be printed. Couple this with sed
, and you would get the required lines.
grep -A 4 pattern input.txt | sed -e '2,4d'
Using sed
, we delete the from the second line until the fourth.
Method 3
sed -n 's/^[ t]*/; /img class="devil_icon/,+4 { 3,5d ; p }' input.txt
I’m simply adding a deletion of the appropriate lines, before printing { 3,5d ; p }
.
Method 4
Here’s a way in Perl which can deal with an arbitrary number of matching lines:
perl -ne '/pattern/ && do{$c=$.; print}; $.==$c+4 && print' file > new_file`
In Perl. the special variable $.
is the current line number. So, each time I find a line matching pattern
, I print it and save its line number as $c
. I then print again when the current line number is 4 more than the one printed previously.
Method 5
awk 'c&&!--c;/img class="devil_icon/{c=4};/img class="devil_icon/' input.txt
You’re essentially doing a find and replace. You can add just a find into the same command and it’ll print both of them 🙂
awk 'c&&!--c;/pattern/{c=4};/pattern/' input.txt
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0