Share your knowledge at the LQ Wiki.
Go Back > Forums > Non-*NIX Forums > Programming
User Name
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.


  Search this Thread
Old 02-12-2012, 01:14 AM   #1
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:

Word2 Word3
Word4 Word5
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, 01:21 AM   #2
Registered: Jun 2007
Location: South Africa
Distribution: Linux Mint,Fedora, openSUSE, RHEL, SLES, Scientific Linux
Posts: 70

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

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, 01:29 AM   #3
Senior Member
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 3,321

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

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

Rep: Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981Reputation: 1981
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.

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):
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.

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 03:55 AM.
Old 02-12-2012, 07:27 AM   #6
Nominal Animal
Senior Member
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 946Reputation: 946Reputation: 946Reputation: 946Reputation: 946Reputation: 946Reputation: 946Reputation: 946
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.)
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)
        printf("%s%s", replacement, RT)
    {   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
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)
        printf("%s%s%s", replacement, $0, RT)
    {   printf("%s%s", $0, RT) }
' input-file > output-file

Last edited by Nominal Animal; 02-13-2012 at 12:15 PM.


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
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 01:04 AM
sed to change patterns on multiple lines neuroimager Linux - General 4 12-08-2010 12:02 PM
split very large 200mb text file by every N lines (sed/awk fails) doug23 Programming 8 08-10-2009 07:08 PM
Replacing text on specific lines with sed or awk? Lantzvillian Linux - Newbie 5 10-17-2007 10:00 AM > Forums > Non-*NIX Forums > Programming

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

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