
Hallo zusammen, aus der sed-Doku werde ich grad nicht recht schlau, vielleicht kann mir hier jemand helfen: Es soll ein html-Code umgestriegelt werden. Der sieht so aus: <header...> <nochwas...> <wieder was...> <tr> <was wichtiges in vielen Zeilen> <tr> <blabla> <nochwas...> <wieder was...> Wie kann man alles vor dem ersten <tr> und alles nach dem letzten <tr> rausschneiden? -- Andre Tann -- 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

Am Dienstag, 4. November 2008 schrieb Andre Tann:
(...) Wie kann man alles vor dem ersten <tr> und alles nach dem letzten <tr> rausschneiden?
Ich bin mir ziemlich sicher, so etwas mal mit den Block-Konstrukten von sed gemacht zu haben, finde aber leider die entsprechenden Skripte nicht mehr. Hier der IIRC relevante Teil der sed-FAQ: http://www.linuxtopia.org/online_books/linux_tool_guides/the_sed_faq/sedfaq4... HTH Jan -- Individualists Unite! -- 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 Andre! On Tue, 04 Nov 2008, Andre Tann wrote:
Es soll ein html-Code umgestriegelt werden. Der sieht so aus:
<header...> <nochwas...> <wieder was...> <tr> <was wichtiges in vielen Zeilen> <tr> <blabla> <nochwas...> <wieder was...>
Wie kann man alles vor dem ersten <tr> und alles nach dem letzten <tr> rausschneiden?
sed -n '/<tr>/,/<\/tr>/p' datei Mit freundlichen Grüßen Christian -- The real trick is this: to keep the lines as short as possible and keep the size the same yet free from the need for hyphena- Dammit!! (Matthew Winn) -- 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

Christian Brabandt, Dienstag, 4. November 2008 10:58:
sed -n '/<tr>/,/<\/tr>/p'
Oops, ziemlich kurz... Es funktioniert auch nicht bei mir, es kommt gar kein Output raus. Könntest Du bitte den Gedankengang kurz erklären? -- Andre Tann -- 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 Andre! On Tue, 04 Nov 2008, Andre Tann wrote:
Christian Brabandt, Dienstag, 4. November 2008 10:58:
sed -n '/<tr>/,/<\/tr>/p' | | ^ print | /Pattern/ beschreibt die Ende-Adresse /Pattern/ beschreibt die Anfang Adresse
Oops, ziemlich kurz... Es funktioniert auch nicht bei mir, es kommt gar kein Output raus. Könntest Du bitte den Gedankengang kurz erklären?
Alle Zeilen, die durch <tr> und </tr> gematcht werden sollen ausgegeben werden. Das -n sorgr dafür, dass nur dann was ausgegeben wird, wenn man explizit durch das print Kommando verlangt. In deinem Beispiel hattest Du erwähnt, du wolltest alles zwischen <tr> ausgeben. Da ich von html ausging, hab ich das Pattern mal auf <tr> </tr> erweitert. Falls das falsch war, lass das \/ im Ende Pattern weg. Mit freundlichen Grüßen Christian -- echo 16i[q]sa[ln0=aln100%Pln100/snlbx]sbA0D4D465452snlb xq |dc -- 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 Tue, Nov 04, 2008 at 09:58:21AM +0100, Andre Tann wrote:
Wie kann man alles vor dem ersten <tr> und alles nach dem letzten <tr> rausschneiden?
Bitte sehr, unelegant aus dem Kopf zusammengehackert: #!/usr/bin/perl -wT while (<>) { if (/\<tr\>/) { print; while (<>) { if (/\<tr\>/) {print; exit; } print; } } } In ein File kopieren, chmod +x <file> und aufrufen mittels: cat <zu bearbeitende Datei> | <dieser_script> > datei -- 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 Tue 04 Nov 2008, Andre Tann wrote:
Es soll ein html-Code umgestriegelt werden. Der sieht so aus:
<header...> <nochwas...> <wieder was...> <tr> <was wichtiges in vielen Zeilen> <tr> <blabla> <nochwas...> <wieder was...>
Wie kann man alles vor dem ersten <tr> und alles nach dem letzten <tr> rausschneiden?
Also, ich glaube nicht, daß Du wirklich willst, wonach Du hier fragst, denn 1) eine Tabellenzeile beginnt zwar mit <tr ...>, endet aber mit </tr>. 2) tr kann groß und klein geschrieben sein. 3) man darf in HTML Tabellen verschachteln, also <table><tr><td><table>...</table></td></tr></table> 4) öffnendes <tr> und schließendes </tr> dürfen auf der selben Zeile stehen. Aber trotzdem, eine kurze Lösung in Perl: perl -e 'undef $/; $_=<>; s/\A.*?(<tr>)/$1/is; s/(<tr>)((?!<tr>).)*? \z/$1/is; print' input_file Das Ding kannst Du auch als Filter benutzen, also command | perl ... Dabei liest Perl das gesamte File erstmal ein, schneidet dann vorn und hinten ab, so wie Du es wolltest, und schreibt den Rest nach stdout. Dein File sollte daher nicht wesentlich größer als Dein RAM sein. Beispiel: echo -e 'huhu\n<tr>\nblub\nblub\n</tr>\nnochwas\n<TR>\nblub\nblub\n</TR>\nund schluss' | perl -e 'undef $/; $_=<>; s/\A.*?(<tr>)/$1/is; s/(<tr>) ((?!<tr>).)*\z/$1/is; print' <tr> blub blub </tr> nochwas <TR> Falls Du doch lieber zeilenweise arbeiten willst, könnte Dich das hier interessieren: perl -ne 'print if /<tr\b/i../<\/tr\b/i' Beispiel: echo -e 'huhu\n<tr class="hugo">\nblub\nblub\n</tr >\nnochwas\n<TR class="hugo">blub blub</TR >\nund schluss' | perl -ne 'print if /<tr\b/i../<\/tr\b/i' <tr class="hugo"> blub blub </tr > <TR class="hugo">blub blub</TR > Dieses kurze Kommando gibt Dir die Tabellenzeilen in einer HTML Datei aus, berücksichtigt aber nicht verschachtelte Tabellen und solchen Kram. Wenn Du es "richtig" machen, also die HTML Struktur berücksichtigen willst, kommst Du wohl um das Perl-Modul HTML::TreeBuilder nicht herum. Kommt halt darauf an, ob Du ein Tool schreibst, das Du öfters benutzen willst, oder ob es nur ein einmaliger Aufruf ist. Letzteres ist vielleicht mit vi sogar schneller erledigt. 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, Dienstag, 4. November 2008 15:38:
On Tue 04 Nov 2008, Andre Tann wrote:
Also, ich glaube nicht, daß Du wirklich willst, wonach Du hier fragst, denn
Ich schon...
1) eine Tabellenzeile beginnt zwar mit <tr ...>, endet aber mit </tr>
Klar, da hast Du recht. Ich habe mich, das gebe ich unumwunden zu, verschrieben.
. 2) tr kann groß und klein geschrieben sein. 3) man darf in HTML Tabellen verschachteln, also <table><tr><td><table>...</table></td></tr></table> 4) öffnendes <tr> und schließendes </tr> dürfen auf der selben Zeile stehen.
All das in der Tat der Fall, und trotzdem: es soll alles _vor_ dem ersten <tr>, und alles _nach_ dem letzten </tr> raus, egal was dazwischen steht, egal, ob groß oder klein, und egal, wie es angeordnet ist.
Aber trotzdem, eine kurze Lösung in Perl:
perl -e 'undef $/; $_=<>; s/\A.*?(<tr>)/$1/is; s/(<tr>)((?!<tr>).)*? \z/$1/is; print' input_file
Da ich mich ja vertippt hatte mit dem </tr>, müßte es also heißen: perl -e 'undef $/; $_=<>; s/\A.*?(<tr>)/$1/is; s/(<tr>)((?!</tr>).)*? \z/$1/is; print' input_file ^ Also nur hier der / Stimmt das? Ich bin in Perl nicht so fit...
Das Ding kannst Du auch als Filter benutzen, also command | perl ... Dabei liest Perl das gesamte File erstmal ein, schneidet dann vorn und hinten ab, so wie Du es wolltest, und schreibt den Rest nach stdout. Dein File sollte daher nicht wesentlich größer als Dein RAM sein.
Sind immer bloß ein paar kB, das ist also kein Problem.
Dieses kurze Kommando gibt Dir die Tabellenzeilen in einer HTML Datei aus, berücksichtigt aber nicht verschachtelte Tabellen und solchen Kram.
Solche Sachen kommen vor, aber es muß so sein, daß es unberücksichtigt bleibt. Es zählt nur das erste und das letzte tr, alles dazwischen ist wichtig und soll bleiben, alles außenrum muß weg. Ich werde Deinen Perl-Schnipsel mal testen, und melde mich dann wieder. Vielen Dank einstweilen! -- Andre Tann -- 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 Tue 04 Nov 2008, Andre Tann wrote:
Da ich mich ja vertippt hatte mit dem </tr>, müßte es also heißen:
perl -e 'undef $/; $_=<>; s/\A.*?(<tr>)/$1/is; s/(<tr>)((?!</tr>).)*? \z/$1/is; print' input_file ^ Also nur hier der /
Stimmt das? Ich bin in Perl nicht so fit...
Also ich erklär's ein bissel. Den echo-Befehl kennst Du ja sicher. echo 'huhu <tr> blub blub </tr> nochwas <TR> blub blub </TR> und schluss' | perl -e ' undef $/; # perl soll das gesamte File lesen $_=<>; # lies das File nach $_ s/\A.*?(<tr>)/$1/is; # siehe 1) s/(<\/tr>)((?!<\/tr>).)*\z/$1/is; # siehe 2) print' # gebe $_ aus. 1) Wenn nicht anders angegeben arbeiten reg. Ausdrücke auf der Variablen $_. Deshalb haben wir das File auch in diese gelesen. Das erste "s" bedeutet "ersetzen", ähnlich wie in sed. \A kennzeichnet den Anfang des Strings, matcht aber nicht nach einem \n innerhalb. Von da an wird alles bis zum ersten <tr> gelesen <tr> selbst landet in $1 (wegen der Klammern). Die beiden Buchstaben "is" nach dem letzten / sind Flags. "i" sagt, daß Groß- und Kleinschreibung nicht unterschieden werden. D.h <TR> würde auch passen. Laß es einfach weg, wenn es stört. "s" ist wichtig. Das bedeutet, daß "." auch auf \n paßt. Wenn Du das "?" wegmachen würdest, wäre "*" greedy (gefräßig). D.h. er würde nicht bis zum ersten <tr>, sondern zum letzten fressen. 2) Der Gedanke hier ist folgender, finde ein </tr> und danach bis zum Stringende keine Stelle, an der ein </tr> beginnt. \z bezeichnet das Stringende. (<\/tr>) kannst Du sicher selbst erklären. Bleibt also ((?!<\/tr>).)*. Zuerst die innere Klammer ?! leitet einen negativen Lookahead ein, guckt also, ob an dieser Stelle der angegebene String nicht beginnt. Der Punkt nach der inneren ) frißt ein Zeichen. Die äußere Klammer brauche ich, um den Lookahead und den Punkt zusammenzufassen. Das mit dem Abschneiden ist hier übrigens buchstäblich gemeint. 2) schneidet auch ein abschließendes \n ab. Falls Du das brauchst, benutze "perl -le" statt "perl -e". 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
participants (5)
-
Andre Tann
-
Christian Brabandt
-
Heinz Diehl
-
Jan Ritzerfeld
-
Torsten Foertsch