LinuxQuestions.org
Help answer threads with 0 replies.
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 01-02-2009, 02:24 PM   #1
Yalla-One
Member
 
Registered: Oct 2004
Location: Norway
Distribution: Slackware, CentOS
Posts: 635

Rep: Reputation: 35
Delete next line in sed


So I've stumbled across another challenge on my adventure towards full sed understanding.

Let's say I want to delete all lines ending with "The END" that follow a line ending in "FOLLOW ME"

Should it not be possible to:

Code:
/FOLLOW ME$/{
N
s/\(.*\)\n.*The END/\1/
}
clearly not, since it won't work...

So then I tought, maybe it's possible to just give a delete command /d , but then I couldn't make it test for the end of the line....

Any takers? Thanks in advance!

-y1

Last edited by Yalla-One; 01-02-2009 at 02:25 PM. Reason: typo
 
Old 01-02-2009, 03:22 PM   #2
taylor_venable
Member
 
Registered: Jun 2005
Location: Indiana, USA
Distribution: OpenBSD, Ubuntu
Posts: 892

Rep: Reputation: 41
I have to say, I learned a lot about sed by solving this one!
Code:
/FOLLOW ME$/ {
    p
    c\

    n
    bx
}

p
d

:x
{
    /The END$/ ! p
    c\

    n
    bx
}
It's kind of a cheap move since sed is stateless, but what we basically do is find the "FOLLOW ME" then enter into a loop constantly clearing and replacing the contents of the pattern space with the next line. This only goes through as many cycles as there are lines before the "FOLLOW ME", then after that it loops within the current cycle gathering up lines until EOF.

Note that this would be much more clearly implemented in awk, but since you asked for sed...

Last edited by taylor_venable; 01-02-2009 at 03:25 PM. Reason: Added explanation.
 
Old 01-02-2009, 05:36 PM   #3
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Arch/XFCE
Posts: 17,802

Rep: Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729
Quote:
Originally Posted by taylor_venable View Post
I have to say, I learned a lot about sed by solving this one!
Me too....

Code:
sed '/follow me/,${/the end$/d}'
This works from the first instance of "follow me" to the end of the file
 
Old 01-02-2009, 05:43 PM   #4
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Arch/XFCE
Posts: 17,802

Rep: Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729
Just realized a semantic ambiguity.....my solution starts on the first instance of "follow me", and then deletes all instances of "the end" at the end of subsequent lines.

If you meant delete lines ending in "the end" ONLY if the immediately follow one with "follow me", then my solution does not work
 
Old 01-02-2009, 08:36 PM   #5
taylor_venable
Member
 
Registered: Jun 2005
Location: Indiana, USA
Distribution: OpenBSD, Ubuntu
Posts: 892

Rep: Reputation: 41
Ha ha! The simple solution completely evaded me! At least the incredibly over-engineered solution provides a starting point for doing more complex things like only deleting lines which appear immediately after "FOLLOW ME" but I must confess I wasn't considering this when I spent fifteen minutes writing it.

I have to say I was very pleased when I found out you can use labels and branches in sed. Crazy.

Edit: Ooh, I just tested my complicated solution with GNU sed and it does... basically nothing. Upon further investigation, it seems that GNU sed never branches down to the label after reading "FOLLOW ME"; a new cycle starts immediately after the n command. The posted solution works correctly with BSD sed (or at least the one in OpenBSD).

Last edited by taylor_venable; 01-02-2009 at 09:07 PM. Reason: Add GNU sed caveat.
 
Old 01-03-2009, 11:12 AM   #6
makyo
Member
 
Registered: Aug 2006
Location: Saint Paul, MN, USA
Distribution: {Free,Open}BSD, CentOS, Debian, Fedora, Solaris, SuSE
Posts: 719

Rep: Reputation: 72
Hi.

Posts that include a sample data set and desired output (inside CODE tags) help to avoid ambiguity (but may also avoid the flights of serendipitous learning while chasing the ambiguity ) ... cheers, makyo
 
Old 01-03-2009, 08:26 PM   #7
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Arch/XFCE
Posts: 17,802

Rep: Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729
Another solution, assuming that we want to delete only the line immediately after the one with "follow me", if said line has "the end" at the end:

Code:
sed '/follow me/{n; /the end$/d}'
 
Old 01-04-2009, 01:37 PM   #8
Yalla-One
Member
 
Registered: Oct 2004
Location: Norway
Distribution: Slackware, CentOS
Posts: 635

Original Poster
Rep: Reputation: 35
Quote:
Originally Posted by pixellany View Post
Another solution, assuming that we want to delete only the line immediately after the one with "follow me", if said line has "the end" at the end:

Code:
sed '/follow me/{n; /the end$/d}'
Perfect! I didn't realize I could nest the "search items" within a begin. This hit the spot perfectly.

Thanks much to everyone who came with ideas - much appreciated!

-y1
 
Old 01-04-2009, 04:29 PM   #9
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
What about http://www.unixguide.net/unix/perl_oneliners.shtml ->

Code:
# delete all but lines beween START and END
   perl -i.old -ne 'print unless /^START$/ .. /^END$/' foo.txt
- this, of course, is not 'sed', but do you really care ?
 
Old 01-04-2009, 05:00 PM   #10
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Arch/XFCE
Posts: 17,802

Rep: Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729Reputation: 729
Quote:
Originally Posted by pixellany View Post
Another solution, assuming that we want to delete only the line immediately after the one with "follow me", if said line has "the end" at the end:

Code:
sed '/follow me/{n; /the end$/d}'
I found a flaw in this:

If you have a line with "follow me", and then the next line does NOT contain "the end", it fails on the next cycle.

This appears to fix the issue, but I'm not done testing:

Code:
sed ':here /follow me/{n; /the end$/d; b here}'
 
  


Reply

Tags
sed


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 to delete a line for a word and line above cmontr Programming 11 07-03-2008 09:33 AM
SED - Delete line above or below as well as matching line... OldGaf Programming 7 06-27-2008 12:51 AM
Delete a line using sed kushalkoolwal Programming 2 09-29-2007 08:25 PM
using sed to delete line to the right khairilthegreat Linux - Newbie 5 07-28-2007 03:10 PM
trying to delete a line with sed deoren Linux - General 2 01-03-2005 10:26 PM


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

Main Menu
Advertisement
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