it-swarm.com.de

Wie ersetze ich rekursiv Zeichen durch sed?

Ist es möglich, Vorkommen einer Zeichenfolge rekursiv zu ersetzen, ohne dieselbe Folge erneut zu durchlaufen?

Durch Ausführen einer sed wie in den folgenden Szenarien kann ich die erwähnte Ausgabe erhalten.

$ echo XX | sed -e 's/XX/XoX/g'
XoX  
$ echo XXX | sed -e 's/XX/XoX/g'
XoXX  
$ echo XXXX | sed -e 's/XX/XoX/g'
XoXXoX  

Ich erwarte jedoch, dass die Ausgabe dem folgenden Verhalten folgt.

Eingang:

XX
XXX
XXXX

Erwartete Ausgabe:

XoX
XoXoX
XoXoXoX

Kann man mit sed alleine das erwartete Verhalten erreichen?

13

Du kannst tun:

> echo XXXX | sed -e ':loop' -e 's/XX/XoX/g' -e 't loop'
XoXoXoX

Mit:

  • -e ':loop': Erstellen Sie ein "Loop" -Label
  • -e 't loop': Springe zum Label "loop", wenn die vorherige Ersetzung erfolgreich war
24
Gohu

In diesem speziellen Fall wäre ein Blick nach vorn oder nach hinten nützlich. Ich denke, GNU sed unterstützt diese nicht. Mit Perl:

Perl -ne 's/X(?=X)/Xo/g; print;'

Sie können auch lookbehind und lookahead wie folgt verwenden:

s/(?<=X)(?=X)/o/g

Woher:

(?<=X) ist ein positiver Lookbehind, eine Behauptung der Länge Null, die sicherstellt, dass wir ein X vor der aktuellen Position haben
(?=X) ist ein positiver Lookahead, eine Behauptung der Länge Null, die sicherstellt, dass wir nach der aktuellen Position ein X haben

Verwendung in einem Perl-Einzeiler:

Perl -pe 's/(?<=X)(?=X)/o/g' inputfile

Woher:

-p veranlasst Perl, eine Schleife um das Programm mit einem impliziten Ausdruck der aktuellen Zeile anzunehmen

10

Die Schleifenantwort ist die allgemeine Methode, um das zu tun, wonach Sie fragen.

Wenn Sie jedoch für Ihre Daten GNU verwenden, können Sie einfach Folgendes tun:

sed 's/\B/o/g'

Die Optionen \b und \B sind reguläre Ausdrücke :

  • \b stimmt mit Wortgrenzen überein, d. h. dem Übergang von einem "Wort" -Zeichen zu einem "Nicht-Wort" -Zeichen oder umgekehrt
  • \B stimmt mit dem Gegenteil von \b überein. d.h. die Lücken "innerhalb" der Wörter. Auf diese Weise können wir nach Bedarf Zeichen in ein Word einfügen, jedoch nicht außerhalb.

Probieren Sie es online aus .

Dies setzt voraus, dass die eingegebenen Zeichen tatsächlich alle "Wort" -Zeichen sind.


Alternativ können Sie Ihr Ziel auch ohne Schleife erreichen, wenn Sie GNU sed nicht haben oder wenn die eingegebenen Zeichen nicht alle "Word" -Zeichen sind:

sed 's/./&o/g;s/o$//'

Dies setzt einfach eine o hinter jedes Zeichen und entfernt dann die letzte o aus der Zeichenkette.

Probieren Sie es online aus .

5
Digital Trauma

Ich habe geprüft, ob es irgendeine Art von Flagge gibt, die dies ermöglicht.
Auch wenn dieses Verhalten vorhanden war, wird es sehr ressourcenintensiv sein.

In diesem speziellen Anwendungsfall ist es jedoch möglich, den Ausdruck nur zweimal zu haben und die erforderliche Funktionalität zu erzielen. mit 2 wiederholten sed Ausdrücken.

echo XX | sed -e 's/XX/XoX/g' -e 's/XX/XoX/g'     # outputs XoX
echo XXX | sed -e 's/XX/XoX/g' -e 's/XX/XoX/g'    # outputs XoXoX
echo XXXX | sed -e 's/XX/XoX/g' -e 's/XX/XoX/g'   # outputs XoXoXoX
4