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 "Schleife", wenn die vorherige Ersetzung erfolgreich war
Ist es möglich, Vorkommen einer Zeichenfolge rekursiv zu ersetzen, ohne erneut über dieselbe Folge zu iterieren?
Durch Ausführen eines 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?
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 "Schleife", wenn die vorherige Ersetzung erfolgreich warIn diesem speziellen Fall wäre Vorausschau oder Rückblick hilfreich. Ich denke, GNU sed
unterstützt diese nicht. Mit perl
:
perl -ne 's/X(?=X)/Xo/g; print;'
Sie könnten auch lookbehind und lookahead verwenden :
s/(?<=X)(?=X)/o/g
Woher:
(?<=X)
ist ein positiver Look hinter, eine Zusicherung der Länge Null, die sicherstellt, dass wir ein X haben, bevor die aktuelle Position eine positive Vorausschau ist, eine Zusicherung der Länge
(?=X)
Null, die sicherstellt, dass nach der aktuellen Position ein X steht
Verwendung in einem Perl-Einzeiler:
perl -pe 's/(?<=X)(?=X)/o/g' inputfile
Woher:
-p
bewirkt, dass Perl eine Schleife um das Programm mit einem impliziten Ausdruck der aktuellen Zeile annimmt
Die Antwort auf die Schleife ist der allgemeine Weg, um das zu tun, was Sie fragen.
Wenn Sie jedoch GNU verwenden, können Sie Folgendes tun:
sed 's/\B/o/g'
Die Optionen \b
und \B
sind reguläre Ausdrücke :
\b
passt zu Wortgrenzen, dh dem Übergang von einem "Wort" -Zeichen zu einem "Nicht-Wort" -Zeichen oder umgekehrt\B
entspricht dem Gegenteil von \b
. dh die Lücken "in" Wörtern. Dies erlaubt uns, Zeichen in ein Wort einzufügen, aber nicht außerhalb, je nach Bedarf.Dies setzt voraus, dass die eingegebenen Zeichen tatsächlich alle "Wort" -Zeichen sind.
Alternativ, wenn Sie nicht über GNU sed verfügen oder wenn die Eingabezeichen nicht alle "Wort" -Zeichen sind, können Sie Ihr Ziel auch ohne Schleife erreichen:
sed 's/./&o/g;s/o$//'
Dies setzt einfach ein o
Zeichen nach jedem Zeichen und entfernt dann das Finale o
aus der Zeichenfolge.
Ich habe geprüft, ob es eine Art Flagge gibt, die dies ermöglicht.
Selbst wenn dieses Verhalten dort 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 erreichen. dh mit 2 sich wiederholenden 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