1

I need to replace within a little bash script a string inside a file but... I am getting weird results.

Let's say I want to replace:

<tag><![CDATA[text]]></tag>

With:

<tag><![CDATA[replaced_text]]></tag>

Should I use sed? I think due to / and [ ] I am getting weird results...

What would be the best way of approaching this?

stealthyninja
  • 10,343
  • 11
  • 51
  • 59
jsjc
  • 1,003
  • 2
  • 12
  • 24

4 Answers4

4

Perl with -p option works almost as sed and it has \Q (quote) switch for its regexes:

perl -pe 's{\Q<tag><![CDATA[text]]></tag>}
           {<tag><![CDATA[replaced_text]]></tag>}' YOUR_FILE

And in Perl you can use different punctuation to delimiter your expressions (s{...}{...} in my example).

yazu
  • 4,462
  • 1
  • 20
  • 14
  • +1 for literal strings. This would be even more excellent if anyone has a link to how to escape the original or replacement text to avoid embedded occurrences of `\E` or other special sequences. – l0b0 Apr 11 '12 at 10:04
3

Yes, you need to escape the brackets, and either escape slashes or use different delimiters.

sed 's,<tag><!\[CDATA\[text\]\]></tag>,<tag><!\[CDATA\[replaced)text\]\]></tag>,'

That said, SGML and XML are not actually any better than HTML when it comes to using regexes; don't expect this to generalize.

Community
  • 1
  • 1
geekosaur
  • 59,309
  • 11
  • 123
  • 114
0

This should be enough:

$ echo '<tag><![CDATA[text]]></tag>' | sed 's/\[text\]/\[replaced_text\]/'
<tag><![CDATA[replaced_text]]></tag>


You can also change your / separator inside sed to a different character like ,, | or %.

Mihai
  • 2,125
  • 2
  • 14
  • 16
0

Just use a delimiter other than /, here I use #:

sed -i 's#<tag><!\[CDATA\[text\]\]></tag>#<tag><![CDATA[replaced_text]]></tag>#g' filename

-i to have sed change the file instead of printing it out. g is for matching more than once (global).

But do you know the exact string you want to match, both the tag and the text? For instance, if you want to replace the text in all with your replaced_text:

perl -i -pe 's#(<tag><!\[CDATA\[)(.*?)(\]\]></tag>)#\1replaced_text\3#g' filename

Switched to perl because sed doesn't support non-greedy multipliers (the *?).