it-swarm.com.de

Sed Ausdruck verstehen, um das letzte Wort aus jeder Zeile durch das erste zu ersetzen

Ich muss das letzte Wort aus jeder Zeile durch das erste ersetzen. Der Code lautet:

$ sed "s/\(^a-z,0-9]*\)\(.*\)\([a-z,0-9]*$\)/\1\2\1\g". 

Ich verstehe diesen Teil nicht \(^a-z,0-9]*\)\(.*\)\([a-z,0-9]*$\) insbesondere \(.*\).

4
L.Robert

Nach der Korrektur der grundlegenden Syntaxfehler haben Sie:

sed "s/\(^[a-z,0-9]*\)\(.*\)\([a-z,0-9]*$\)/\1\2\1/g"
  • s/old/new/ ersetze old durch new
  • \(^[a-z,0-9]*\) Speichern Sie eine beliebige Anzahl von Kleinbuchstaben oder Ziffern am Zeilenanfang (^ ist Zeilenanfang) für später (Referenz später mit \1)
  • \(.*\) Speichern Sie eine beliebige Anzahl von Zeichen für später (als \2)
  • \([a-z,0-9]*$\) Speichern Sie eine beliebige Anzahl von Kleinbuchstaben oder Ziffern am Ende der Zeile ($ ist das Ende der Zeile) für spätere Zwecke (Referenz als \3).
  • \1\2\1 druckt das erste Muster, dann das zweite und dann das erste erneut
  • g Dies ist in diesem Ausdruck unangemessen. Dies bedeutet, dass mehrere Übereinstimmungen in derselben Zeile bearbeitet werden müssen, aber unser Ausdruck muss die gesamte Zeile lesen. Daher macht g keinen Sinn und sollte weggelassen werden.

Dies wird immer noch nicht funktionieren, da reguläre Ausdrücke gierig sind. Daher stimmt das mittlere \(.*\) mit allem nach dem ersten Wort überein, was dazu führt, dass das erste Wort am Ende der Zeile erneut gedruckt wird, ohne etwas zu ersetzen.

Sie können das Problem beheben (indem Sie auch I für die Suche ohne Berücksichtigung der Groß-/Kleinschreibung hinzufügen):

sed "s/\(^[a-z,0-9]*\) \(.*\) \([a-z,0-9]*$\)/\1 \2 \1/I"

Wenn Sie neben Buchstaben und Zahlen weitere Zeichen einfügen möchten:

sed -r 's/^([^ ]+) (.*) ([^ ]+)$/\1 \2 \1/'
  • -r use ERE (spart mit all diesen Backslashes)
  • [^ ]+ mindestens eines der Zeichen außer Leerzeichen
10
Zanna

Ich glaube nicht, dass Ihr Code hier überhaupt funktionieren wird, weil er einfach fehlerhaft ist. Ich würde den gesamten Ausdruck umschreiben. Angenommen, alle Zeilen beginnen und enden mit Wörtern, die nur Zahlen und Buchstaben aus dem Alphabet enthalten, könnten Sie Folgendes versuchen:

$ echo -en "foo bar baz\nThe Good, the Bad and the Ugly\n" | \
> sed 's/^\(\<[[:alpha:]]\+\>\)\(.*\)\<[[:alpha:]]\+\>$/\1\2\1/g'
foo bar foo
The Good, the Bad and the The

Kurze Erklärung:

s/PATTERN/SUBSTITUTION_STRING/g - PATTERN ist das, wonach wir suchen, und SUBSTITUTION_STRING ist das, womit wir dieses Muster ersetzen werden. g bedeutet, dass die gesamte Zeile gescannt wird und nicht nur die erste Übereinstimmung auf der Zeile.

^\(\<[[:alpha:]]\+\>\) - Wenn eine Zeile mit einer Wortgrenze beginnt, auf die mehr als ein alphanumerisches Zeichen gefolgt von einer anderen Wortgrenze folgt, speichern Sie alles in der Variablen \1.

\<[[:alpha:]]\+\>$ - genau dasselbe, aber wir verwenden es nur, um den Ort des letzten Wortes zu identifizieren.

\(.*\) - alles dazwischen wird in der Variablen \2 gespeichert.

\1\2\1 - Die gleiche Zeile mit dem letzten Wort wird durch das erste Wort ersetzt.

3
misha