RegExp-Problem(e)
Steffen Velte
- perl
0 LanX0 Cheatah0 LanX0 Steffen Velte0 Cheatah
Hallo,
habe ein Problem mit folgendem reg. Ausdruck. Eigentlich will ich Zeilenumbrüche innerhalb eines HTML-Tags entfernen. Später sollte also - wenn man die Variable $file ausgibt - <TABLE NAME="1-2"> in einer Zeile stehen...
$file='
<HTML>
<BODY>
<TABLE
NAME="1-2">
<TR>
<TD>1:1</TD>
<TD>1:2</TD>
</TR>
</TABLE>
</BODY>
</HTML>
';
$file =~ s/(<.*[^>])\n(.*>)/$1 $2/igs;
Ausserdem habe ich einen anderen regulären Ausdruck der funktioniert, allerdings will ich genau das Gegenteil davon. Dachte mir, anstelle von $file =~ s/.../.../; - $file !~ s/.../.../; zu schreiben. Funktioniert aber auch nicht, genauer gesagt ist das Ergebnis das gleiche!?
Wie negiert man denn sonst einen regulären Ausdruck?
Hoffe mir ist zu helfen ;-)
Viele Grüsse,
Steffen Velte
Hi Steffen
$file =~ s/(<.*[^>])\n(.*>)/$1 $2/igs;
(<.*[^>]) verstehe ich nicht!
was passiert bei (ungetestet)
s/(<.*?)\n(.*?>)/$1 $2/igs;
Evtl kannste dich auch mit der m option auseinandersetzen.
Viele Grüsse,
Rolf
Hi,
$file =~ s/(<.*[^>])\n(.*>)/$1 $2/igs;
das /s bewirkt, daß auch "." auf "\n" matcht - und genau das willst Du nicht. Außerdem ist ".*[^>]" sinnarm - Du suchst damit beliebig viele Zeichen (also vom Anfang des Strings bis fast am Ende), gefolgt von einem Zeichen, welches nicht ">" sein darf.
Eigentlich suchst Du "(<[^>]+)". In der zweiten Klammer solltest Du vom "?" Gebrauch machen, um bei .* die Greediness auszuschalten.
Wie negiert man denn sonst einen regulären Ausdruck?
Bei der Prüfung, ob ein String auf eine RegExp matcht (also "ja" oder "nein"), mit "!~". Darüber hinaus macht der Begriff "Negierung" keinen Sinn, weil es um Aktionen, Anzahlen oder reelle Werte geht.
Cheatah
Hi Cheatah
Eigentlich suchst Du "(<[^>]+)". In der zweiten Klammer solltest Du vom "?" Gebrauch machen, um bei .* die Greediness auszuschalten.
Jetzt mal ne rein stilistische Frage, wozu [^>] und ? in einem ausdruck mischen?
ich meine
entweder
(<[^>]+)\n([^<]*>)
oder gleich
(<.+?)\n(.*?>)
wobei ich letzteres klar favorisieren würde, man braucht ja nicht
auf ewig abwärtskompatibel zu sed zu bleiben.
Qapla'
Rolf
Hi,
Eigentlich suchst Du "(<[^>]+)". In der zweiten Klammer solltest Du vom "?" Gebrauch machen, um bei .* die Greediness auszuschalten.
Jetzt mal ne rein stilistische Frage, wozu [^>] und ? in einem ausdruck mischen?
"[^>]" in der ersten, und ".*?" in der zweiten Klammer.
(<[^>]+)\n([^<]*>)
Tja, in der zweiten Klammer ist es Dir eigentlich egal, ob ein "<" auftaucht... hauptsache, es wird das erste ">" gefunden.
(<.+?)\n(.*?>)
Das kann zu unschönen Effekten führen, wenn z.B. das nächste "\n" gesucht wird, obwohl davor ein ">" steht. Dies vermeidest Du mit "[^>]+".
wobei ich letzteres klar favorisieren würde, man braucht ja nicht
auf ewig abwärtskompatibel zu sed zu bleiben.
Das hat mit Abwärtskompatibilität genauso wenig zu tun, wie mit "Stil 1 oder Stil 2". Einzelne Tokens haben einfach bestimmte Bedeutungen, und diese sollte man so gut und sicher wie möglich nutzen.
Cheatah
Hi Cheatah,
(<[^>]+)\n([^<]*>)
und
(<.+?)\n(.*?>)
haben IMHO bei validen HTML und dieser Aufgabenstellung den gleichen Effekt.
(Ausnahme Javascriptcode mit "<" oder ">")
Kannste mal ein Beispiel posten der einen unterschiedlichen Effekt erzeugt?
Viele Grübel
Rolf
Hi Cheatah,
Nach vielem Grübeln hab ich doch einen Vorteil deines Ansatzes entdeckt:
(<[^>]+)\n(.*?>)
ermöglicht es auch Tags mit mehr als einem Zeilenumbruch zu fassen,
da [^>]+ alle \n bis auf den letzten schluckt.
Das absolut sicherste dürfte es sein ein entsprechendes Perlmodul
zu nutzen, dass letztens hier erwähnt wurde, alldieweil Javascriptcode
auftauchen könnte.
Bye
Rolf
Thnx,
_der_ Ausdruck steht jetzt, aber...
Eigentlich suchst Du "(<[^>]+)". In der zweiten Klammer solltest
Du vom "?" Gebrauch machen, um bei .* die Greediness auszuschalten.
Ich befolge Deinen Rat. Wovor hat er mich genau bewahrt?
ob ein String auf eine RegExp matcht (also "ja" oder "nein"),
mit "!~".
Das funktioniert bei mir nicht. Aber, ich checke erst noch mal den Ausdruck...
Darüber hinaus macht der Begriff "Negierung" keinen Sinn, weil es
um Aktionen, Anzahlen oder reelle Werte geht.
Klar, Du hast prinzipiell Recht. Allerdings hat sich das schon eingebürgert, z.B. in "PERL in 21 Tagen" von Laura Lemay wird es so bezeichnet.
Ciao,
Steffen
Hi,
Eigentlich suchst Du "(<[^>]+)". In der zweiten Klammer solltest
Du vom "?" Gebrauch machen, um bei .* die Greediness auszuschalten.
Ich befolge Deinen Rat. Wovor hat er mich genau bewahrt?
z.B. davor, daß die zweite Klammer auf "...><bla>...</bla>" matcht.
ob ein String auf eine RegExp matcht (also "ja" oder "nein"),
mit "!~".
Das funktioniert bei mir nicht.
#!/usr/bin/perl -w
use strict;
my $string = 'Hallo';
print "a\n" if ($string =~ /a/);
print "kein b\n" if ($string !~ /b/);
Allerdings hat sich das schon eingebürgert, z.B. in "PERL in 21 Tagen" von Laura Lemay wird es so bezeichnet.
In welchem Zusammenhang genau? (Ich hab das Buch nicht.)
Cheatah
Hallo...
Du vom "?" Gebrauch machen, um bei .* die Greediness
auszuschalten.
Ich befolge Deinen Rat. Wovor hat er mich genau bewahrt?
z.B. davor, daß die zweite Klammer auf "...><bla>...</bla>"
matcht.
Muss ich noch mal drüber nachdenken...
ob ein String auf eine RegExp matcht (also "ja"
oder "nein"),
Das funktioniert bei mir nicht.
#!/usr/bin/perl -w
use strict;
my $string = 'Hallo';
print "a\n" if ($string =~ /a/);
print "kein b\n" if ($string !~ /b/);
Ok, das funktioniert. Ich habe bestimmt einen Fehler im Ausdruck... Mal sehen, ich kriege das schon hin.
Allerdings hat sich das schon eingebürgert, z.B. in "PERL in
21 Tagen" von Laura Lemay wird es so bezeichnet.
In welchem Zusammenhang genau? (Ich hab das Buch nicht.)
Habe das Buch nicht hier im Büro, daher kann ich den genauen Wortlaut jetzt nicht wiedergeben. Aber Lemay verwendet defintiv Negieren genau in diesem Zusammenhang, also das Gegenteil eines regulären Ausdruckes zu suchen...
Lt. Duden ist Negieren gleichbedeutend mit Verneinen, also sicher nicht der passende Ausdruck dafür...
Nochmals danke für Deine Hilfe...
Ciao,
Steffen