12 Stimmen

Wie verwendet man den Befehl sed, um eine Zeichenkette vor einer Musterzeichenkette hinzuzufügen?

Ich möchte sed verwenden, um meine Datei mit dem Namen "baz" zu ändern.

Wenn ich ein Muster foo suche, ist foo nicht am Anfang oder Ende der Zeile, ich möchte bar vor foo anhängen, wie kann ich es mit sed tun?

Input file named baz:
blah_foo_blahblahblah
blah_foo_blahblahblah
blah_foo_blahblahblah
blah_foo_blahblahblah

Output file 
blah_barfoo_blahblahblah
blah_barfoo_blahblahblah
blah_barfoo_blahblahblah
blah_barfoo_blahblahblah

21voto

paxdiablo Punkte 809679

Sie können einfach etwas verwenden wie:

sed 's/foo/barfoo/g' baz

(die g am Ende bedeutet global, jedes Vorkommen in jeder Zeile und nicht nur das erste).

Für ein willkürlich (statt eines festen) Musters wie foo[0-9] können Sie Erfassungsgruppen wie folgt verwenden:

pax$ echo 'xyz fooA abc
xyz foo5 abc
xyz fooB abc' | sed 's/\(foo[0-9]\)/bar\1/g'

xyz fooA abc
xyz barfoo5 abc
xyz fooB abc

Die Klammern erfassen den tatsächlichen Text, der mit dem Muster übereinstimmt, und die \1 verwendet es bei der Substitution.

Sie können beliebig komplexe Muster verwenden und dabei auch sicherstellen, dass nur vollständige Wörter übereinstimmen. Ändern Sie zum Beispiel das Muster nur, wenn es unmittelbar von einer Wortgrenze umgeben ist:

pax$ echo 'xyz fooA abc
xyz foo5 abc foo77 qqq xfoo4 zzz
xyz fooB abc' | sed 's/\(\bfoo[0-9]\b\)/bar\1/g'

xyz fooA abc
xyz barfoo5 abc foo77 qqq xfoo4 zzz
xyz fooB abc

In Bezug auf die Funktionsweise der Erfassungsgruppen können Sie Klammern verwenden, um den Text, der mit einem Muster übereinstimmt, zur späteren Verwendung in der Ersetzung zu speichern. Die erfassten Bezeichner basieren auf dem ( Zeichen von links nach rechts zu lesen, so dass die Regex (ich habe das \ Escape-Zeichen entfernt und der Übersichtlichkeit halber ein wenig aufgefüllt):

( ( \S* )   ( \S* ) )
^ ^     ^   ^     ^ ^
| |     |   |     | |
| +--2--+   +--3--+ |
+---------1---------+

bei Anwendung auf den Text Pax Diablo würden Sie drei Gruppen erhalten:

\1 = Pax Diablo
\2 = Pax
\3 = Diablo

wie unten dargestellt:

pax$ echo 'Pax Diablo' | sed 's/\(\(\S*\) \(\S*\)\)/[\1] [\2] [\3]/'
[Pax Diablo] [Pax] [Diablo]

3voto

Einfach Ersatz den Beginn der Linie mit etwas anderem.

sed '/^foo/s/^/bar/'

0voto

tripleee Punkte 155951

Um alle "foo" außer am Anfang oder Ende der Zeile zu ersetzen oder zu ändern, würde ich vorschlagen, sie am Anfang und Ende der Zeile vorübergehend durch einen eindeutigen Sentinel-Wert zu ersetzen.

sed 's/^foo/____veryunlikelytoken_bol____/
  s/foo$/____veryunlikelytoken_eol____/
  s/foo/bar&/g
  s/^____veryunlikelytoken_bol____/foo/
  s/____veryunlikelytoken_eol____$/foo/'

En sed gibt es keine Möglichkeit, "kann hier nicht passen" anzugeben. In Perl regex und Derivaten (d.h. Sprachen, die von Perls regex abgeleitet sind, nicht notwendigerweise Sprachen, die von Perl abgeleitet sind) gibt es verschiedene negative Assertions, so dass man etwas wie folgt tun kann

perl -pe 's/(?!^)foo(?!$)/barfoo/g'

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X