Sed - Ersetzen Sie ein Zeichen in einer übereinstimmenden Zeile?

21

In einer Datei mit Zeilen wie dieser:

# lorem ipsum blah variable

Ich möchte ein #(Kommentar-) Zeichen in derselben Zeile entfernen , die eine bestimmte Zeichenfolge enthält. Ist sedgut dafür

Ich kämpfe darum, dass diese Bedingung funktioniert. Ich habe eine "ungeschickte" Art, dies zu tun; Ich kann die übereinstimmende Zeilennummer mit awkoder finden sedund diese Nummer dann in einem separaten sedBefehl verwenden, aber ich glaube, dass dies viel besser gemacht werden kann.

Kamil
quelle

Antworten:

36

Verwenden Sie die gesuchte Zeichenfolge als Auswahl für die zu bearbeitenden Zeilen:

sed '/ipsum/s/#//g'

/ipsum/Wählt Zeilen aus, die "ipsum" enthalten, und nur in diesen Zeilen werden die folgenden Befehle ausgeführt. Sie können geschweifte Klammern verwenden, um weitere Befehle auszuführen

/ipsum/{s/#//g;s/@/-at-/g;}
peterph
quelle
4
Genau; Dies ist die beste Antwort (obwohl nicht die einzige). Kommentare: (1) 's/#//g'entfernen werden alle die #Zeichen in der Zeile. Wenn Sie das nicht möchten, entfernen Sie das g(was für "global" steht). (2) Um eine Datei an Ort und Stelle zu bearbeiten (wie in der Frage gefordert), verwenden Sie sed -i.
G-Man sagt, dass Monica
2
(3) Wenn Sie in der Praxis eine Zeile sed -i '/ipsum/s/#[[:space:]]*//'auskommentieren möchten, möchten Sie möglicherweise Leerzeichen und Tabulatoren entfernen, die unmittelbar auf die Zeile folgen #. (4) Möglicherweise möchten Sie auch prüfen, ob #das erste nicht leere Zeichen in der Zeile ist. Der aktuelle Befehl würde das #aus der Zeile löschen prompt "Enter # of ipsums:".
G-Man sagt, dass Monica
1
@ G-Man - tolle Ergänzung! Zu deinem 2. Punkt (führendes Leerzeichen), was ist mit: sed -i '/ipsum/s/^#[[:space:]]*//'?! ( ^bedeutet Beginn der Zeile, $für das Ende der Zeile) - zumindest in Gnu Sed ...
Jeremy Davis
1
@JeremyDavis: Ja, man könnte den Regex auf den Anfang der Zeile Anker mit ^, aber das wäre falsch. Ich kommentiere eingerückten Code oft aus, indem ich #den Code unmittelbar vor den Code setze, damit der Code #eingerückt wird. Ich bezweifle, dass ich die einzige Person bin, die das tut.
G-Man sagt, dass Monica
1
@ G-Man - ach ja, natürlich! Danke, das hatte ich nicht bedacht. So würden Sie auch zwischen Auf Leerzeichen überprüfen möchten ^und #so etwas wie folgt aus : /ipsum/{/^[[:space:]]*#/s/#[[:space:]]*//}. Obwohl dies auch dann #noch Probleme verursachen kann (z. B. in Sprachen, die Leerzeichen verwenden) , je nachdem, wo sich das befindet.
Jeremy Davis
7
$ cat input.txt
# lorem ipsum blah variable
# lorem ipsum blat variable
# lorem ipsum blow variable
# lorem ipsum blip variable
# lorem ipsum blue variable

dann:

$ sed 's|# \(.*blue.*\)|\1|' input.txt

gibt:

# lorem ipsum blah variable
# lorem ipsum blat variable
# lorem ipsum blow variable
# lorem ipsum blip variable
lorem ipsum blue variable

Es funktioniert wie folgt:

Das ssagt, seddass es ersetzen soll, was der reguläre Ausdruck findet.

Das Muster setzt # \(.*blue.*\)sich wie folgt zusammen: Finden Sie einen Hash, gefolgt von einem Leerzeichen. Die Klammer ( \() startet die Gruppierung. .*blue.*ist das Wort bluemit irgendetwas davor und danach. Die nächste Klammer ( \)) schließt die Gruppierung.

Der Ersatz ist \1ein Rückverweis auf den Inhalt der ersten Gruppierungsklammer.

garethTheRed
quelle
3

Sie können Vim im Ex-Modus verwenden:

ex -sc '/ipsum/s/#//|x' file
  1. s Ersatz

  2. x speichern und schließen

Steven Penny
quelle
Das ist ziemlich cool. Das wusste ich nicht! TBH, ich bin mir nicht sicher, ob es die beste Antwort auf diese Frage ist (IMO ist die führende Antwort), aber es ist immer noch sehr cool! Danke fürs Schreiben.
Jeremy Davis