it-swarm.com.de

Wie man das Ende der Linie mit sed erkennt

Ich suche nach einer Möglichkeit, das Ersetzen nur auszuführen, wenn das letzte Zeichen eine neue Zeile ist, wobei sed verwendet wird.

Zum Beispiel:

lettersAtEndOfLine

wird ersetzt, aber das ist nicht:

lettersWithCharacterAfter&

Da sed mit Zeilenumbrüchen nicht gut funktioniert, ist es nicht so einfach wie

$ sed -E "s/[a-zA-Z]*\n/replace/" file.txt

Wie kann dies erreicht werden?

Mit Standard sed sehen Sie nie eine neue Zeile im Text, der aus einer Datei gelesen wird. Dies liegt daran, dass sed Zeile für Zeile liest und daher am Ende des Textes der aktuellen Zeile im Musterbereich von sed keine neue Zeile steht. Mit anderen Worten, sed liest durch Zeilenumbrüche getrennte Daten, und die Trennzeichen sind nicht Teil dessen, was ein sed -Skript sieht.

Reguläre Ausdrücke können verankert am Ende der Zeile mit $ (Oder am Anfang mit ^) Sein. Wenn Sie einen Ausdruck am Anfang/Ende einer Zeile verankern, wird er genau dort und nicht nur irgendwo in der Zeile angezeigt.

Wenn Sie etwas, das dem Muster [A-Za-z]* Am Ende der Zeile entspricht, durch etwas ersetzen möchten, verankern Sie das Muster wie folgt:

[A-Za-z]*$

... wird es zwingen, am Ende der Zeile und nirgendwo anders übereinzustimmen.

Da jedoch [A-Za-z]*$ Auch mit nichts übereinstimmt (z. B. die leere Zeichenfolge am Ende von jede Zeile), müssen Sie den Abgleich von - erzwingen. etwas, z durch Angabe

[A-Za-z][A-Za-z]*$

oder

[A-Za-z]\{1,\}$

Ihre Kommandozeile sed lautet also

$ sed 's/[A-Za-z]\{1,\}$/replace/' file.txt

Ich habe den Schalter -E Hier nicht verwendet, weil er nicht benötigt wird. Damit hättest du schreiben können

$ sed -E 's/[A-Za-z]+$/replace/' file.txt

Es ist Geschmackssache.

21
Kusalananda
sed "s/[a-zA-Z]*$/replace/" input.txt > result.txt

Oder der lange komplexe unnötige Weg:

Ich habe herausgefunden, dass dies mit Hilfe von tr unter Verwendung von sed möglich ist. Sie können ein anderes Zeichen zuweisen, um das Ende der Zeile darzustellen. Ein anderes temporäres Zeichen muss verwendet werden, in diesem Fall "` ". Verwenden wir "~", um das Ende der Zeile darzustellen:

tr '\n' '`' <input.txt >output.txt
sed -i "s/`/~`/" output.txt
tr '`' '\n' <output.txt >result.txt

Und um dann die eigentliche Suche und Ersetzung durchzuführen, verwenden Sie "~" anstelle von "\ n":

sed -i -E "s/[a-zA-Z]*~/replace/" result.txt

Und dann bereinigen Sie das zusätzliche Zeichen in den anderen Zeilen:

sed -i "s/~//" result.txt

Offensichtlich kann dies alles zusammen geleitet werden, was zu etwas führt wie:

tr '\n' '`' <input.txt | sed -e "s/`/~`/" | tr '`' '\n' | sed -E -e "s/[a-zA-Z]*~/replace/" | sed "s/~//" > result.txt

Um das Zeilenende zu finden, verwenden Sie einfach das $ - Zeichen:

Ohne Zeilenende Anker:

sed -n '/pattern/p' file 

Ohne Zeilenende Anker:

sed -n '/pattern$/p' file
0
user unknown

Aus dem (defekten) Code-Snippet, das Sie gepostet haben, möchten Sie anscheinend auch die neue Zeile ersetzen. In diesem Fall kann Ihnen die Regex-Verankerung an sich nicht helfen. Folgendes ist eine Lösung:

sed '/[[:alpha:]]\+$/{N;s/[[:alpha:]]\+\n/replace/}' your_file

Heruntergebrochen:

  • /[a-zA-Z]\+$/{} bedeutet, dass alles, was in den Locken enthalten ist, auf Linien angewendet wird, die mit dem regulären Ausdruck übereinstimmen.
  • Der Regex ist derjenige, der die Verankerung verwendet, wie in Ihre eigene Antwort zu sehen, geändert, um Glenn Jackmans Kommentare zu berücksichtigen.
  • Innerhalb der Locken bedeutet N "die nächste Zeile an den aktiven Puffer anhängen" (was sed den "Musterraum" nennt)
  • Endlich, das s/// Anweisung ist Ihre erforderliche Ersetzung. Es funktioniert jetzt, weil der Musterraum zwei aufeinanderfolgende Zeilen enthält und die neue Zeile daher ein Teil davon ist.
0
Joseph R.