sed find and replace between two tags with multi line
Using sed
you can try something like:
sed -e ':a;N;$!ba' -e 's#<file.*</file>#<sometext>\nvalue1\n</sometext>#' file
My sed
is a little rusty but what we are doing here is using :a;N;$!ba
we effectively create one long line in pattern space so that we can apply the second expression which does your substitution.
This will probably need GNU sed
Test:
$ cat file
hold1
hold2
<file option1='one'>
some text
some text
more data
</file>
this1
that1
$ sed -e ':a;N;$!ba' -e 's#<file.*</file>#<sometext>\nvalue1\n</sometext>#' file
hold1
hold2
<sometext>
value1
</sometext>
this1
that1
Grep/Sed between two tags with multiline
I'd use pcregrep
, which can match multiline regexes:
pcregrep -Mo 'test \K((?s).)*?(?=</singleline>)' filename
The tricks are:
-M
allowspcregrep
to match on more than one line,-o
makes it print only the match,\K
throws away the part of the match that comes before it,(?=</singleline>)
is a lookahead term that matches an empty string if (and only if) it is followed by</singleline>
, and((?s).)*?
to match any characters non-greedily, which is to say that if you have several occurrences of</singleline>
in the file, it will match until the closest rather than the furthest. If this is not desired, remove the?
.(?s)
enables thes
option locally for the term to make.
match newlines in it; it wouldn't do that by default.
Thanks to @CasimiretHippolyte for pointing out the ((?s).)
alternative to (.|\n)
.
sed to match multiline range and replace
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 s
ubstitute 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 containssecond:
:a
- set a label nameda
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 labela
positions#"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
.
Sed regexp multiline - replace HTML
While @nhahtdh's answer is the correct one for your original question, this solution is the answer to your comments:
sed '
/<!-- PAGE TAG -->/,/<!-- PAGE TAG -->/ {
1 {
s/^.*$/Replace Data/
b
}
d
}
'
You can read it like so:
/<!-- PAGE TAG -->/,/<!-- PAGE TAG -->/
-> for the lines between these regexes
1 {
-> for the first matching line
s/^.*$/Replace Data/
-> search for anything and replace with Replace Data
b
-> branch to end (behaves like break in this instance)
d
-> otherwise, delete the line
You can make any series of sed commands into one-liners with gnu sed by adding semicolons after each command (but it's not recommended if you want to be able to read it later on):
sed '/<!-- PAGE TAG -->/,/<!-- PAGE TAG -->/ { 1 { s/^.*$/Replace Data/; b; }; d; };'
Just as a side note, you should really try to be as specific as possible in your posting. "replaced/removed" means "replaced OR removed". If you want it replaced, just say replaced. That helps both those of us trying to answer your question and future users who might be experiencing the same issue.
Use sed to Replace Multiple Lines
This might work for you (GNU sed):
sed '/second/,/fourth/cfound' file
or for those line numbers:
sed '2,4cfound' file
Replace a word with multiple lines using sed?
If you build your multiple line text with "\n
"s, this will work with a simple sed
command as:
DATA=`echo ${DATA} | tr '\n' "\\n"`
#now, DATA="line1\nline2\nline3"
sed "s/_data_/${DATA}/" mail.tpl
Related Topics
Shuffle Output of Find with Fixed Seed
Can Someone Explain the Shell Shock Bash Code
Wget: Unsupported Scheme on Non-Http Url
Arm: Disabling Mmu and Updating Pc
Average of Multiple Files Without Considering Missing Values
How to Update a Varible from One Shell to Another Shell
Overriding the Variable in Distro.Conf Config File in Custom Image Recipe Yocto
Embed All External References When Creating a Static Library
How to Get the Output of Ansible Ad-Hoc Command in JSON, CSV or Other Format
Django on Apache Wtih Mod_Wsgi (Linux) - 403 Forbidden
Glassfish There Is a Process Already Using the Admin Port 4848
Extracting Variable in Yaml from a Shell Script
Script to Check for Process & Restart Program If Not Found
Filter a Content File to Table