LinuxQuestions.org
View the Most Wanted LQ Wiki articles.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 09-29-2008, 02:54 PM   #1
DX398
LQ Newbie
 
Registered: Jul 2008
Posts: 7

Rep: Reputation: 0
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
 
Old 09-29-2008, 03:06 PM   #2
CRC123
Member
 
Registered: Aug 2008
Distribution: opensuse, RHEL
Posts: 374
Blog Entries: 1

Rep: Reputation: 31
If you're not trying to replace any of the text, then the grep command has an option to do this:
Code:
grep -B 3 "192.168.12.11" <file.txt> > outfile.txt
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.
 
Old 09-30-2008, 08:25 AM   #3
DX398
LQ Newbie
 
Registered: Jul 2008
Posts: 7

Original Poster
Rep: Reputation: 0
Thanks crc123, but is there anyway SED can do this?
 
Old 09-30-2008, 08:38 AM   #4
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Arch/XFCE
Posts: 17,802

Rep: Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728
Quote:
Originally Posted by DX398 View Post
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.

I visualize some messy-looking code....

Really good SED tutorial here:
http://www.grymoire.com/Unix/Sed.html
 
Old 09-30-2008, 08:55 AM   #5
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Arch/XFCE
Posts: 17,802

Rep: Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728
Look what I found:
http://www.grymoire.com/Unix/Sed.html#uh-54
He calls it "context grep"
 
Old 09-30-2008, 09:01 AM   #6
keefaz
Senior Member
 
Registered: Mar 2004
Distribution: Slackware
Posts: 4,537

Rep: Reputation: 119Reputation: 119
Maybe this could work:
Code:
sed -n '/Host Name/,/192.168.12.111/p' input.txt > output.txt
 
Old 09-30-2008, 09:04 AM   #7
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Arch/XFCE
Posts: 17,802

Rep: Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728
I think OP wanted the 3 previous lines without knowing the content...ie the only thing known was the desired pattern in the last line.
 
Old 09-30-2008, 09:32 AM   #8
ghostdog74
Senior Member
 
Registered: Aug 2006
Posts: 2,695
Blog Entries: 5

Rep: Reputation: 241Reputation: 241Reputation: 241
Quote:
Originally Posted by DX398 View Post
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
the order is jumbled, but you get the picture.
 
Old 09-30-2008, 10:22 AM   #9
radoulov
Member
 
Registered: Apr 2007
Location: Milano, Italia/Варна, България
Distribution: Ubuntu, Open SUSE
Posts: 212

Rep: Reputation: 35
If the file is not too large:

Code:
perl -0ne'print /((?:.*\n){3}.*search pattern.*\n)/g' filename

Last edited by radoulov; 09-30-2008 at 10:26 AM.
 
Old 09-30-2008, 11:08 AM   #10
DX398
LQ Newbie
 
Registered: Jul 2008
Posts: 7

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by pixellany View Post
I think OP wanted the 3 previous lines without knowing the content...ie the only thing known was the desired pattern in the last line.

That's correct, I don't know the value of the previous lines.
 
Old 09-30-2008, 11:25 AM   #11
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Arch/XFCE
Posts: 17,802

Rep: Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728
I finally figured out the original syntax:

Code:
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

Last edited by pixellany; 09-30-2008 at 11:27 AM.
 
Old 09-30-2008, 12:19 PM   #12
Kenhelm
Member
 
Registered: Mar 2008
Location: N. W. England
Distribution: Mandriva
Posts: 329

Rep: Reputation: 140Reputation: 140
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)

Last edited by Kenhelm; 09-30-2008 at 01:20 PM.
 
Old 10-01-2008, 08:25 AM   #13
DX398
LQ Newbie
 
Registered: Jul 2008
Posts: 7

Original Poster
Rep: Reputation: 0
Thank You! I get it now...you guys are amazing!
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
sed or grep : delete lines containing matching text raj000 Linux - General 18 09-08-2012 09:38 AM
Sed: how to delete all lines except those matching........ DX398 Programming 9 07-23-2008 02:39 AM
getting sed to hold lines and print them out again- help please inonzi_prowler Linux - Software 3 02-21-2007 03:26 AM
AWK/SED Multiple pattern matching over multiple lines issue GigerMalmensteen Programming 15 12-03-2006 05:08 PM
awk/gawk/sed - read lines from file1, comment out or delete matching lines in file2 rascal84 Linux - General 1 05-24-2006 09:19 AM


All times are GMT -5. The time now is 07:03 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration