sed über mehrere Zeilen will nicht
Hi, ich hatte es nicht für ein Problem gehalten: sed soll mir in Abhängigkeit von der Verwendung bestimmte Bereiche aus html-Dateien entfernen, die in Kommentare eingeschlossen sind. Die Bereiche können über mehrere Zeilen gehen... müssen aber nicht. Also etwa so: ... blabla<!--START-->das soll raus das auch bis hierher<!--ENDE-->blubblub... ... Ich dachte, ein primitives sed -e 's/<!--START-->.*<!--ENDE-->//g' würde es tun. Tut es aber nicht, auch nicht mit diversen Quotings. Es erwischt nur Bereiche, die in einer Zeile liegen. Irgendwo hab ich ein Brett vorm Kopf. Sed ist gnu sed 4.1.5, das OS 11.1 Original. Thx für jeden Schubs in die richtige Richtung... jth -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
On Wed 23 Sep 2009, Joerg Thuemmler wrote:
ich hatte es nicht für ein Problem gehalten: sed soll mir in Abhängigkeit von der Verwendung bestimmte Bereiche aus html-Dateien entfernen, die in Kommentare eingeschlossen sind. Die Bereiche können über mehrere Zeilen gehen... müssen aber nicht. Also etwa so: ... blabla<!--START-->das soll raus das auch bis hierher<!--ENDE-->blubblub... ... Ich dachte, ein primitives
sed -e 's/<!--START-->.*<!--ENDE-->//g'
würde es tun. Tut es aber nicht, auch nicht mit diversen Quotings. Es erwischt nur Bereiche, die in einer Zeile liegen. Irgendwo hab ich ein Brett vorm Kopf.
Sed arbeitet ZEILENWEISE. Nimm doch einfach Perl: echo -e 'a<a>\nbb\ncc</a>d x<a>\nbb\ncc</a>y' | perl -pe 'BEGIN {undef $/} s!<a>.*?</a>!!gs' $ echo -e 'a<a>\nbb\ncc</a>d x<a>\nbb\ncc</a>y' a<a> bb cc</a>d x<a> bb cc</a>y $ echo -e 'a<a>\nbb\ncc</a>d x<a>\nbb\ncc</a>y' |
perl -pe 'BEGIN {undef $/} s!<a>.*?</a>!!gs' ad xy
Torsten -- Need professional mod_perl support? Just hire me: torsten.foertsch@gmx.net -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
Torsten Foertsch schrieb:
On Wed 23 Sep 2009, Joerg Thuemmler wrote:
ich hatte es nicht für ein Problem gehalten: sed soll mir in Abhängigkeit von der Verwendung bestimmte Bereiche aus html-Dateien entfernen, die in Kommentare eingeschlossen sind. Die Bereiche können über mehrere Zeilen gehen... müssen aber nicht. Also etwa so: ... blabla<!--START-->das soll raus das auch bis hierher<!--ENDE-->blubblub... ... Ich dachte, ein primitives
sed -e 's/<!--START-->.*<!--ENDE-->//g'
würde es tun. Tut es aber nicht, auch nicht mit diversen Quotings. Es erwischt nur Bereiche, die in einer Zeile liegen. Irgendwo hab ich ein Brett vorm Kopf.
Sed arbeitet ZEILENWEISE.
Ja, das wußte ich... dachte nur, es gäbe einen Trick, das zu umgehen
Nimm doch einfach Perl:
echo -e 'a<a>\nbb\ncc</a>d x<a>\nbb\ncc</a>y' | perl -pe 'BEGIN {undef $/} s!<a>.*?</a>!!gs'
$ echo -e 'a<a>\nbb\ncc</a>d x<a>\nbb\ncc</a>y' a<a> bb cc</a>d x<a> bb cc</a>y
$ echo -e 'a<a>\nbb\ncc</a>d x<a>\nbb\ncc</a>y' |
perl -pe 'BEGIN {undef $/} s!<a>.*?</a>!!gs' ad xy
Torsten
Danke, Torsten, perl ist nicht mein Ding, aber ich sehe immer wieder, dass vieles damit sehr schnell geht... zumindest diesen Schnipsel versuche ich mal zu verstehen ;-) Danke jedenfalls cu jth -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
Joerg Thuemmler schrieb:
Torsten Foertsch schrieb:
On Wed 23 Sep 2009, Joerg Thuemmler wrote:
ich hatte es nicht für ein Problem gehalten: sed soll mir in Abhängigkeit von der Verwendung bestimmte Bereiche aus html-Dateien entfernen, die in Kommentare eingeschlossen sind. Die Bereiche können über mehrere Zeilen gehen... müssen aber nicht. Also etwa so: ... blabla<!--START-->das soll raus das auch bis hierher<!--ENDE-->blubblub... ... Ich dachte, ein primitives
sed -e 's/<!--START-->.*<!--ENDE-->//g'
würde es tun. Tut es aber nicht, auch nicht mit diversen Quotings. Es erwischt nur Bereiche, die in einer Zeile liegen. Irgendwo hab ich ein Brett vorm Kopf. Sed arbeitet ZEILENWEISE.
Ja, das wußte ich... dachte nur, es gäbe einen Trick, das zu umgehen
Mir fallen zwei Möglichkeiten: 1. Wenn sichergestellt werden kann, dass vor bzw. nach der jeweiligen Bereichsmarkierung kein weiterer Text steht: sed -e '/ANFANG/,/ENDE/d' 2. Verwende ein Script: #!/usr/bin/sed -f /ANFANG/,/ENDE/{ /ANFANG/!{ /ENDE/!d } /ANFANG/,s/\(.*\)ANFANG.*/\1/g /ENDE/,s/.*ENDE\(,*\)/\1/g } Mach das Script ausführbar und ruf es mit der Quelle auf. (Das geht sicher auch auch der Kommando-Zeile, ist so aber leichter zu lesen;-) Warnung: Ich kenne mich mit sed auch nicht so gut aus, also Vorsicht beim ausprobieren! Es gibt auch noch den Befehl N, mit dem eine Zeile angehängt und so über Zeilengrenzen hinweg gearbeitet werden kann. Musste ich aber bisher noch nicht anwenden. Mit freundlichen Grüßen Martin Blank -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
On Wed 23 Sep 2009, Joerg Thuemmler wrote:
Sed arbeitet ZEILENWEISE.
Ja, das wußte ich... dachte nur, es gäbe einen Trick, das zu umgehen
Den gibt es, den "hold space". Dort kannst Du Zwischenergebnisse speichern. h, g und x heißen die Kommandos, um damit zu arbeiten. Aber laß Dir sagen, das wird ein GEFRIEMEL bis das richtig funktioniert, insbesondere, wenn Du nicht jeden Tag sed programmierst. Torsten -- Need professional mod_perl support? Just hire me: torsten.foertsch@gmx.net -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
Hallo, Am Mit, 23 Sep 2009, Torsten Foertsch schrieb:
On Wed 23 Sep 2009, Joerg Thuemmler wrote:
Sed arbeitet ZEILENWEISE.
Ja, das wußte ich... dachte nur, es gäbe einen Trick, das zu umgehen
Den gibt es, den "hold space". Dort kannst Du Zwischenergebnisse speichern. h, g und x heißen die Kommandos, um damit zu arbeiten.
Aber laß Dir sagen, das wird ein GEFRIEMEL bis das richtig funktioniert, insbesondere, wenn Du nicht jeden Tag sed programmierst.
Ist gar nicht so schwierig: sed -n ' /<!--START-->/,/<!--ENDE-->/ { H; }; /<!--ENDE-->/ { x; s/<!--START-->.*<!--ENDE-->//; p; q; }' HTH, -dnh --
Ich hätte auch nie geglaubt, das es 10 Minuten dauern kann, bis jemand ohne Fehler einmal ein lspci -v fehlerfrei eingegeben hat. Hast Du auch erwähnt, daß man anschließend die RETURN-Taste drücken muß? [> Torsten Hallmann und Bernd Brodesser in suse-linux] -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
Hi David! On Mi, 23 Sep 2009, David Haller wrote:
Ist gar nicht so schwierig:
Da wäre ich mir nicht so sicher ;)
sed -n ' /<!--START-->/,/<!--ENDE-->/ { H; }; /<!--ENDE-->/ { x; s/<!--START-->.*<!--ENDE-->//; p; q; }'
#v+ ~$ sed ':' foobar 1111<!--START-->ccccc<!--ENDE-->99999<!--START-->bbbbb<!--ENDE-->aaaa 3333<!--START-->bbbb bbbb bbb b<!--ENDE-->6666 letzte Zeile ~$ sed -n ' /<!--START-->/,/<!--ENDE-->/ { H; }; /<!--ENDE-->/ { x; s/<!--START-->.*<!--ENDE-->//; p; q; }' foobar 1111aaaa ~$ #v- Das Problem ist wohl das q command. Das sollte wohl ein n sein? Und dann werden auch noch nicht die Zeilen ausgegeben, die außerhalb eines Start/Stop Blocks stehen. Oder sollte das nur das erste Start/Ende Vorkommen ersetzen? Das hier funktioniert dagegen bei meinen kurzen Tests, ist aber auch nicht gerade schön: #v+ ~$ sed ' /<!--START-->/{ b loop } :loop { /<!--ENDE-->/b subst N b loop } :subst { s/<!--START-->.*<!--ENDE-->// }' foobar 1111aaaa 33336666 letzte Zeile ~$ #v- Und dann hat man immer noch das Problem mit der Greediness. Ich glaube für Multiline-Patterns sollte man eher auf eine richtige Scriptsprache zurückgreifen. Mit awk sollte das ziemlich einfach zu machen sein (und vor allem viel lesbarer! Aber awk kann auch keine non-greedy Patterns, oder?) Oder natürlich Perl. Den Einzeiler hatten wir ja schon ;) (Aber wie geht es in Perl, wenn man nicht die komplette Datei einlesen will?) Mit freundlichen Grüßen Christian -- :wq! -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
On Thu 24 Sep 2009, Christian Brabandt wrote:
Aber wie geht es in Perl, wenn man nicht die komplette Datei einlesen will?
Das ist natürlich etwas aufwendiger. Der OP meinte aber, es handle sich um HTML Dateien. Diese sind selten so groß, daß man sie mit aktueller Hardware nicht komplett einlesen kann. Vor 20 Jahren hätte ich es auch anders gelöst. Doch: while echo -e 'a<a>\nbb\ncc</a>d x<a>\nbb\ncc</a>y'; do :; done | perl -pe '$_=$x.$_;s!<a>.*</a>!!gs;s!(<a>.*)!!s;$x=$1;END{print$x}' Ich habe mir erlaubt der besseren Lesbarkeit halber unnötige Leerzeichen wegzulassen, ;-) Torsten -- Need professional mod_perl support? Just hire me: torsten.foertsch@gmx.net -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
On Wed, September 23, 2009 3:24 pm, Joerg Thuemmler wrote:
blabla<!--START-->das soll raus das auch bis hierher<!--ENDE-->blubblub... ... Ich dachte, ein primitives
sed -e 's/<!--START-->.*<!--ENDE-->//g'
würde es tun. Tut es aber nicht, auch nicht mit diversen Quotings. Es erwischt nur Bereiche, die in einer Zeile liegen. Irgendwo hab ich ein Brett vorm Kopf.
Sed ist ein Stream-Editor. Der liest *eine Zeile*, führt die Bearbeitung durch und macht dann weiter mit der nächsten Zeile. Demzufolge kann dein Pattern nicht funktionieren, denn per default hast du immer nur genau eine Zeile im Speicher. Man kann aber sed beibringen, mehrere Zeilen einzulesen. Das ist aber nur sinnvoll, wenn deine zu bearbeitenden Dateien kleiner als dein RAM sind, sonst wird es vermutlich grottig lahm. Diese Methode sollte funktionieren: #v+ sed -e ':x;N;$!bx;s/<!--START-->.*<!--ENDE-->//g' foo #v- Das könnte aber noch an der Greediness scheitern und Dir zu viel wegschnippeln. Die angesprochene Perl-Lösung könnte helfen. Ich würde es wahrscheinlich so machen, oder wenn es quick and dirty sein soll und die Datei nicht zu groß ist Vim mißbrauchen: #v+ vim -u NONE -N -c '%s/<!--START-->\_.\{-}<!--ENDE-->//g|w! output|q!' foo #v- Mit freundlichen Grüßen Christian -- ERROR 047: Keyboard not found. Press RETURN to continue. -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
[... zahlreiche gute Tipps ...] Hi und Danke allen Helfern, ich hab erstmal perl genommen, da ich glaube, den Einzeiler begriffen zu haben ;-) , die anderen Sachen will ich mir sukzessive ansehen, man kann immer was lernen. Aufpassen muss man auf jeden Fall, weil die regex ja das größte mögliche Muster finden und man also immer noch ausschließen muss, dass das Muster selbst innerhalb des Musters vorkommt... Thx an alle cu jth -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
participants (5)
-
Christian Brabandt
-
David Haller
-
Joerg Thuemmler
-
Martin Blank
-
Torsten Foertsch