Sed command to print matching lines and 2 lines above..
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Sed command to print matching lines and 2 lines above..
Hello everyone,
I'm looking to print matching lines including the 3 lines above the matched line. I have come up with the following command but it's only printing 1 line above. In the example below the output is missing the Host Name and the following blank line. Anyone known what I'm missing here?
sed -n /192.168.12/{x;p;x;p};h <input.txt >output.txt
input.txt
Host Name: SERVER1
NetBIOS over TCP/IP: Enabled
IP Address: 192.168.12.111
-----------------------------
output.txt
NetBIOS over TCP/IP: Enabled
IP Address: 192.168.12.111
You may play around with it to get what you want, but the man pages of grep have a section called 'Context Line Control' that discusses what you are trying to do.
Thanks crc123, but is there anyway SED can do this?
The rational answer is: Why?
This said, I will confess that I often do such things---if only to see if it can be done.
The problem with SED is that it operates one line at a time. To do what you want, you have to append lines to the hold register and then pull out the combination to test it. If the test failed, you would then have to delete one of the lines and add a new one.
Thanks crc123, but is there anyway SED can do this?
sed is not the correct tool for such task. there's actually an algorithm for this. It uses variables to store every 3 lines.
Code:
awk '
/pattern/{
print first
print second
print third
}
{
third=second
second=first
first=$0
}
' file
output:
Code:
# more file
this is line 1
this is line 2
this is line 3
this is line 4
search pattern
this is line 5
this is line 6
# ./testnew.sh
this is line 4
this is line 3
this is line 2
sed -n /192.168.12/{x;p;x;p};h <input.txt >output.txt
What this does is to write (copy) each line to the hold buffer until the pattern is found. Then it exchanges the pattern buffer and hold buffer, prints, and then repeats. Thus you get the last thing copied to the hold buffer, and then the line where the pattern matched.
What you need is "H" (append), instead of "h" (copy)
This is crude, but works:
Code:
sed -n '/keyword/{H;g;p};H' filename|tail -n3 > newfilename
In the reference I gave you, read carefully about h, H, g, G, and x
The following is adapted from a sed emulation of the tail command at http://www.gnu.org/software/sed/manual/sed.html#tail
It creates a moving window of four lines.
The '$' end of line marker is essential as the pattern space will usually contain four file lines and '192.168.12.111' could be in any of them, but we only want to print when its in the last one, i.e. at the end of the pattern space.
Code:
sed -n '1h;2,4 {; H; g; };/192.168.12.111$/p;1,3d;N;D' input.txt
This is a more pragmatic method which uses tac (to reverse the order of the lines) and GNU sed:-
Code:
tac input.txt | sed -n '/192.168.12/,+3p' | tac
EDIT:
These solutions give the matched line and the three lines above.
If only two lines above are required change 4 to 3, and 3 to 2 in the code.
(Both versions of the problem appear in the thread)
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.