Shane Warne
Shane Warne

Reputation: 1418

sed to match multiline range and replace

I have the file below

next: 
    {
     host = "http://nxt-newepisode.xcfm.crata.dive.com/err1.2.2/table/kenny.xml.gz"
    };

second:
   {
     host = "http://nxt-secondepisode.xcfm.crata.dive.com/err1.2.2/table/kenny.xml.gz"
    };

I want to replace the url based on nxt:{ host = "" and second: { host = "". How can I filter this using sed with a multiline match, as these are on multiple lines?

I tried:

sed -i '/second : {\rhost/s#"http://.*"#"next.com"#' file.txt

It doesn't work. I am using \r for new line but I also tried \n.

Upvotes: 4

Views: 4903

Answers (2)

potong
potong

Reputation: 58371

This might work for you (GNU sed):

sed -E ':a;/^second:/{:b;n;/^\S+:/ba;/(^\s*host = ")[^"]*/s##\1newUrl#;Tb}' file

The replacement of a new url is confined to the second: section.

On encountering another section the processing is repeated.

Within a second: section the line begining host = " is sought and the value within double quotes replaced.

Otherwise the process is repeated until either condition above is met or the end of file.

Upvotes: 0

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626689

If we can assume you have the URL on the second line below second: you may use

sed -i '/second:/{N;N;s#"http://.*"#"next.com"#}' file

See this online sed demo.

N appends the newline and then subsequent line to the pattern space. So, the substitute command is run on the following text:

second:
   {
     host = "http://nxt-secondepisode.xcfm.crata.dive.com/err1.2.2/table/kenny.xml.gz"

If it is not known which line it is exactly, you may loop before you find the lione that starts with 0+ spaces, then host =, and only then run substitution:

sed -i '/second:/{:a;n;/^ *host *=/!ba;s#"http://.*"#"next.com"#}' file

See this online sed demo.

Here,

  • /second:/ - once a line contains second:
  • :a - set a label named a
  • n - discard the current pattern space and read the next line into it
  • /^ *host *=/!ba - if the line does not (!) start with 0+ spaces, host, 0+ spaces, =, then go back (b) to label a position
  • s#"http://.*"#"next.com"# - run the substitution.

Literal spaces can be replaced with [[:space:]]*, [[:blank:]]* or \s* to match any whitespace depending on what works in your sed.

Upvotes: 4

Related Questions