LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
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 02-12-2012, 12:14 AM   #1
Quon
LQ Newbie
 
Registered: Nov 2011
Posts: 20

Rep: Reputation: 0
How do I replace the text between patterns located on separate lines? (sed, awk, etc)


If I have these words:

Word1
Word2 Word3
Word4 Word5
Word6
Word7
Word8
Word9 Word10

and I want to replace everything between "Word4" and "Word8"

Or, if I want to replace everything after "Word4" (I tried sed 's/Word4*//' but it only works for that line.)
 
Old 02-12-2012, 12:21 AM   #2
rgdacosta
Member
 
Registered: Jun 2007
Location: South Africa
Distribution: Linux Mint,Fedora, openSUSE, RHEL, SLES, Scientific Linux
Posts: 71

Rep: Reputation: 25
If you want your command to work on lines 3 to 6 then you can use something like this:

Code:
sed '3,6 s/Word/Number/' words
Basically, sed conducts the operation on lines 3 to 6. The operation is a substitute and replace which is written to STDOUT so no changes are made to the file.

Hope that's what you wanted.
 
Old 02-12-2012, 12:29 AM   #3
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,863
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
Code:
sed -e '/Word4/,/Word8/c\
New content line1\
New content line2' inputfile >outputfile
 
Old 02-12-2012, 02:08 AM   #4
codemaniac
Member
 
Registered: Feb 2010
Location: INDIA
Distribution: Slackware,Suse,Mint
Posts: 39

Rep: Reputation: 17
Quote:
sed 's/Word[4-8]//g'
This would replace Word4 , Word5, Word6,Word7, and Word8 in your sample input file .
 
Old 02-12-2012, 02:53 AM   #5
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Sed only operates on single lines by default. You have to use addressing, nested commands, and/or multi-line processing to do anything that spans multiple lines.

Check out the sed faq here, specifically sections 4.23 and 4.24.

http://sed.sourceforge.net/sedfaq4.html#s4.23

The exact solution to use depends a lot on what you want the output to look like. Here's one possibility (basically the same as NevemTeve posted above):
Code:
sed '/Word4/,/Word8/ c Word4\nNewWord\nWord8'
This simply replaces the entire matched block with the desired text, including re-inserting the parts of the starting and stopping lines you want to keep.


Here are a few more useful sed references.
http://www.grymoire.com/Unix/Sed.html
http://sed.sourceforge.net/grabbag/
http://sed.sourceforge.net/sed1line.txt


It's often easier to use awk or another tool with better multi-line ability instead.

Last edited by David the H.; 02-12-2012 at 02:55 AM.
 
Old 02-12-2012, 06:27 AM   #6
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by Quon View Post
I want to replace everything between "Word4" and "Word8"
I think you'll get best results with GNU awk. (Any awk variant will work, but GNU awk has the ability to retain the type of whitespace between words.)
Code:
gawk -v startword="Word4" -v endword="Word8" -v replacement="Stuff" '
    BEGIN { RS="[\t\n\v\f\r ]+" ; FS=RS; RT="\n" }
    ($0 == startword) {
        while (getline > 0)
            if ($0 == endword)
                break
        printf("%s%s", replacement, RT)
        next
    }
    {   printf("%s%s", $0, RT) }
' input-file > output-file
If you want to use regular expressions instead of case sensitive string comparisons, replace the two == with ~ .

The BEGIN rule is run before any input is processed. It sets the record (and field) separator to any consecutive whitespace, including newlines. Thus, each word is its own record. For GNU awk, RT is automatically set to the text that matched RS, but other awks don't support it. Like I said, this works best with GNU awk. If you replace gawk with awk it will work with any awk variant, but all words will be split to separate lines.

In awk, $0 refers to the entire input record. Here, it is always the current word, including any punctuation. If the input record matches the start word, the while loop will read records until the end word is found. The replacement is printed, and awk is told to check the next record.

If the input record does not match the start word, the final rule prints it.

Note that the above also replaces the start and end words. If you want to keep them intact, replacing only what is between them, use
Code:
gawk -v startword="Word4" -v endword="Word8" -v replacement="Stuff " '
    BEGIN { RS="[\t\n\v\f\r ]+" ; FS=RS; RT="\n" }
    ($0 == startword) {
        printf("%s%s", $0, RT)
        while (getline > 0)
            if ($0 == endword)
                break
        printf("%s%s%s", replacement, $0, RT)
        next
    }
    {   printf("%s%s", $0, RT) }
' input-file > output-file

Last edited by Nominal Animal; 02-13-2012 at 11:15 AM.
 
  


Reply



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
how do you replace text between two words in a whole file not just 1 line w/ sed/awk lityit Programming 5 11-04-2011 12:04 AM
sed to change patterns on multiple lines neuroimager Linux - General 4 12-08-2010 11:02 AM
split very large 200mb text file by every N lines (sed/awk fails) doug23 Programming 8 08-10-2009 06:08 PM
Replacing text on specific lines with sed or awk? Lantzvillian Linux - Newbie 5 10-17-2007 09:00 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 01:07 PM.

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
Open Source Consulting | Domain Registration