2012-04-09 12 views
1

Ich muss in einem kleinen Bash-Skript eine Zeichenfolge in einer Datei ersetzen, aber ... Ich bekomme seltsame Ergebnisse.Ersetzen String in einer Datei von einem Bash-Skript

Sagen wir, ich ersetzen wollen:

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

mit:

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

Soll ich sed benutzen? Ich denke, aufgrund / und [] ich seltsame Ergebnisse bin immer ...

Was ist die beste Art und Weise der Annäherung an sein würde?

Antwort

3

Ja, Sie müssen den Klammern entkommen und entweder Schrägstriche oder andere Trennzeichen verwenden.

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

Das heißt, SGML und XML sind nicht wirklich besser als HTML, wenn es um die Verwendung Regexes kommt; Erwarte nicht, dass dies verallgemeinert wird.

4

Perl mit Option -p funktioniert fast wie sed und es hat \ Q (Zitat) Schalter für seine reguläre Ausdrücke:

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

Und in Perl können Sie verschiedene Interpunktion verwenden, um Ihre Ausdrücke Trennzeichen (s {.. .} {...} in meinem Beispiel).

+1

+1 für '\ Q'. Um das Zitieren zu beenden, verwenden Sie '\ E' – Gowtham

+0

+1 für literale Strings. Dies wäre sogar noch besser, wenn jemand einen Link dazu hat, wie man den Original- oder Ersetzungstext umgehen kann, um eingebettete Vorkommen von '\ E' oder anderen speziellen Sequenzen zu vermeiden. – l0b0

0

Dies sollte genug sein:

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


Sie auch Ihre / Separator im Inneren wie , auf einen anderen Charakter sed ändern können, | oder %.

0

Nur ein Trennzeichen anders als/verwenden, hier verwende ich #:

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

-i die Datei sed Änderung zu haben, anstatt sie auszudrucken. g ist für mehr als einmal (global) passend.

Aber wissen Sie die genaue Zeichenfolge, die Sie übereinstimmen möchten, sowohl das Tag als auch den Text? Zum Beispiel, wenn Sie den Text in allen mit Ihrem replaced_text ersetzen möchten:

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

Switched weil perl sed nicht nicht gierige Multiplikatoren unterstützt (die *?).