2012-04-02 11 views
9

echo ddayaynightday | sed 's/day//g'Sed Ersatz rekursiv

Es endet daynight

Gibt es trotzdem, um es bis kein Spiel zu machen ersetzen?

+0

wiederholen, bis seine Länge zu ändern stoppt. Ich weiß nicht, wie man das in der Shell macht. – kirilloid

Antwort

17

Meine bevorzugte Form für diesen Fall:

echo ddayaynightday | sed -e ':loop' -e 's/day//g' -e 't loop' 

Dies ist das gleiche wie die alle andere, mit der Ausnahme, dass es mehrere -en verwendet Befehle zu machen die drei Zeilen und verwendet das t Konstrukt - was "Verzweigung, wenn Sie eine erfolgreiche Substitution" - zu iterieren bedeutet.

+1

Gut zu wissen, wie man in der Befehlszeile mehrere Skriptzeilen eingibt, wenn ";" wird nicht funktionieren. Ich würde deine Antwort auch wegen des "t" bedingten Sprungs bevorzugen, der für mich klarer ist, im Gegensatz zu einer Musterübereinstimmung mit einem unbedingten Sprung. –

+0

danke :) Ich denke, das sieht gut aus, nicht sicher, ob es einen besseren Weg gibt mit einigen erweiterten regulären Ex .. – w00d

3

Das Flag g stimmt absichtlich nicht mit dem ersetzten Teil der Zeichenfolge überein. Was Sie tun müssen, ist ein bisschen anders. Versuchen Sie dies:

Aufgrund BSD Sed schrulligen die eingebetteten Zeilenumbrüche sind erforderlich. Wenn Sie GNU Sed verwenden können Sie in der Lage sein, um wegzukommen mit

sed ':begin;/day/{ s///; bbegin }' 
+0

In sh-artigen Shells können Sie auch einfach eine literale Newline in eine Zeichenfolge in Anführungszeichen einfügen. Auf der anderen Seite finde ich die '$' ... Zeichenkette mit Escape ... '' Konstruieren Sie für kurze Skripte wie diese sowieso hübscher. Für wirklich lange Skripte ist die Verwendung von '-f-Datei 'wahrscheinlich besser. In diesem speziellen Fall funktionieren auch mehrere '-e'-Befehle. – torek

+0

@torek: Guter Punkt über die mehreren '-e' Befehle. Ich persönlich hasse das Einbetten von Zeilenumbrüchen in eine Zeichenfolge in Anführungszeichen. Es ist in der Regel schwieriger zu lesen und macht es viel schwieriger, den Befehl mit anderen Personen zu teilen (da Befehle normalerweise auf einer Zeile stehen). –

+0

danke, dein 2. funktioniert nicht auf meinem osx, es druckt einfach die Eingabe – w00d

1

folgende Arbeiten:

$ echo ddayaynightday | sed ':loop;/day/{s///g;b loop}' 
night 

auf Ihrem System Je arbeiten die ; kann keine Befehle zu trennen, so können Sie verwenden Sie die folgende statt:

echo ddayaynightday | sed -e ':loop' -e '/day/{s///g 
               b loop}' 

Erläuterung:

:loop  # Create the label 'loop' 
/day/{  # if the pattern space matches 'day' 
    s///g  # remove all occurrence of 'day' from the pattern space 
    b loop # go back to the label 'loop' 
} 

Wenn der Teil b loop des Befehls nicht ausgeführt wird, wird der aktuelle Inhalt des Musterbereichs gedruckt und die nächste Zeile wird gelesen.

+0

Ordentlich, Alter!321 – Almo

+0

Das funktioniert nicht für mich. Es gibt einen Fehler: "sed: 1:": Schleife;/Tag/{s/Tag // g; b ... ": unbenutzte Bezeichnung 'loop;/Tag/{s/Tag // g; b Schleife} '' – Graham

+0

Semikolon funktioniert nur in einigen Versionen von sed. – torek

0

Ok, hier sind sie: while und strlen in bash. Mit ihnen kann man meine Idee umzusetzen:

Repeat until its length will stop changing.

Es weder Weg, Flagge noch Art und Weise so einzustellen, regex zu schreiben, „bis kein Spiel Ersatz“.

5

Dies könnte für Sie arbeitet:

echo ddayaynightday | sed ':a;s/day//g;ta' 
night 
+0

funktioniert nicht auf meinem osx – w00d

+0

Es scheint, Sie brauchen mehrere '-e' Schalter – potong

+0

Es * funktioniert * auf meinem OSX 10.6.8 – MASL

2

mit bash:

str=ddayaynightday 
while true; do tmp=${str//day/}; [[ $tmp = $str ]] && break; str=$tmp; done 
echo $str