Regex Auswertung
Andres Freund
- perl
Hi
Ich habe einen Text in der Form:(suchtext hat nur eine erkennbare Form, keinen gleichen Inhalt)
texttext <suchtext> textexttext <suchtext> texttext\n
texttexttext <suchtext> <suchtext>texttexttext\n
usw.
Mein Problem ist, dass ich alle gesuchten Texte in einem Array bräuchte, was vom Regex bei einzelnen suchtexten her kein Problem ist.
Mein Problem ist, dass ich den Text zwar finden kann, aber da er mehrmals in einer Zeile vorkommen kann, nicht mit $suche[0] = $1; in das Array bringen kann, da ich dann den später in der Zeile folgenden <suchtext> nicht mehr finden kann, da es führ ihn keinen Bezeichner mehr gibt.
mfg Andres
hi!
texttext <suchtext> textexttext <suchtext> texttext\n
texttexttext <suchtext> <suchtext>texttexttext\n
usw.
Mein Problem ist, dass ich alle gesuchten Texte in einem Array
bräuchte, was vom Regex bei einzelnen suchtexten her kein Problem
ist.
Dazu musst du in jeder Zeile den regulären Ausdruck mehrfach anwenden,
damit du alle Ergebnisse findest. Dazu dient der Modifier "g", den du
als Option bei regulären Ausdrücke angeben kannst. Beispiel:
$text = "bla (treffer 1) laber (treffer 2) blub (treffer 3) und so weiter...";
push @results, $& while $text =~ /(.*?)/g;
print "$_\n" for @results;
Der Text in $text enthält drei Treffer in Klammern, die ich finden
möchte. Dafür verwende ich den regulären Ausdruck /(.*?)/. Das "g"
ist wie erwähnt dafür zuständig, jeden Treffer zu finden, nicht nur
den ersten. Das ganze verpacke ich dann in eine while-Schleife, wobei
ich in jedem Schleifendurchlauf den gefundenen Ausdruck in das Array
@results einfüge. Die letzte Zeile gibt dann den Inhalt dieses Arrays
aus.
bye, Frank!
Hi
Danke, eigentlich ganz logisch, aber ih bin nur nicht auf die Idee mit $& kam ich nicht.(wie vernagelt kann mn eigentlich sein ;-), anscheinend ist Schlaf doch was notwendiges :-)) Nur eine Frage habe ich: Was bringt hier /(.*?)/g; das ?. Das * sagt doch schon dass das davorstehende Zeichen 0-unendlich(65000 irgendwas) mal vorkommen kann,oder?
Mfg Andres
Hallo,
Was bringt hier /(.*?)/g; das ?. Das * sagt doch schon dass das davorstehende Zeichen 0-unendlich(65000 irgendwas) mal vorkommen kann,oder?
* ist gierig, d.h. es 'frißt' so viele Zeichen wie möglich. *? ist die nicht-gierige Variante, es 'frißt' gerade so viel, wie notwendig, um die Regex zu erfüllen.
In Deinem Falle würde * bei 'xx(suchtext)yy(suchtext2)zzzz' '(suchtext)yy(suchtext2)' als einzigen Treffer bringen, während *? zwei Treffer, nämlich '(suchtext)' und '(suchtext2)' bedeuten würde.
Näheres findest Du unter perldoc perlre.
Grüße
Klaus
Hallo Frank,
$text = "bla (treffer 1) laber (treffer 2) blub (treffer 3) und so weiter...";
push @results, $& while $text =~ /(.*?)/g;
print "$_\n" for @results;
Schlechtes Beispiel. Erstens zu kompliziert und zweitens ist die Verwendung
von $& boese[tm], warum kannst du in der perlfaq6 (Abschnitt Why does using $&,
$`, or $' slow my program down?) nachlesen. Drittens hast du einen Quantifier
ungreedy gemacht, was den RegEx auch verlangsamt. Einfacher und schneller waere:
my @results = $text =~ /(([^)]+))/g;
Das geht, weil der m///-Operator im Listenkontext eine Liste zurueck gibt, der
die in Klammern stehenden Matches enthaelt -- in diesem Fall also den gesuchten
Text.
Gruesse,
CK
Mein Problem ist, dass ich den Text zwar finden kann, aber [...]
Der pattern modifier /g (match globally) sollte helfen.
Moin,
wenn der Text zwischen den Suchtexten ähnlich wäre und sich durch einen regulären Ausdruck ersetzen ließe, könntest Du die Funktion split benutzen.
Steht der Suchtext immer in spitzen Klammern, könnte man den Pattern-Matching-Operator anwenden, z. B.
$meintext =~ m/<(.+?)>/;
danach ist $´ der Teil nach dem Suchstring, $` der davor und $& der durch den Matching-Operator gefundene String.
Mein Problem ist, dass ich alle gesuchten Texte in einem Array bräuchte, was vom Regex bei einzelnen suchtexten her kein Problem ist.
push(@array, $&); #sollte eigentlich das tun, was es verspricht
Noch viel Erfolg,
Martin
Hi
Ich habe einen Text in der Form:(suchtext hat nur eine erkennbare Form, keinen gleichen Inhalt)
texttext <suchtext> textexttext <suchtext> texttext\n
texttexttext <suchtext> <suchtext>texttexttext\n
usw.
Mein Problem ist, dass ich den Text zwar finden kann, aber da er mehrmals in einer Zeile vorkommen kann, nicht mit $suche[0] = $1; in das Array bringen kann, da ich dann den später in der Zeile folgenden <suchtext> nicht mehr finden kann, da es führ ihn keinen Bezeichner mehr gibt.
mfg Andres
Hallo,
bitte lies http://learn.to/quote.
wenn der Text zwischen den Suchtexten ähnlich wäre und sich durch einen
regulären Ausdruck ersetzen ließe, könntest Du die Funktion split benutzen.
Das ist gerade *kein* Fall fuer split().
Steht der Suchtext immer in spitzen Klammern, könnte man den
Pattern-Matching-Operator anwenden, z. B.
$meintext =~ m/<(.+?)>/;
Hier fehlt der Modifier 'g'. perldoc perlre
danach ist $´ der Teil nach dem Suchstring, $` der davor und $& der durch
den Matching-Operator gefundene String.
perldoc perlfaq6, Abschnitt "Why does using $&, $`, or $' slow my program
down?".
Gruesse,
CK
Moin,
Dein Einwand
perldoc perlfaq6, Abschnitt "Why does using $&, $`, or $' slow my program
down?".
ist natürlich berechtigt. Wenn man aber kein Programmierer ist, sondern das ganze nur nebenbei und nach Feierabend betreibt, könnte die Verwendung einfacherer Funktionen die Programmpflege erleichtern.
Wenn das Script im Jahr auf dem Server statt 5min 10min CPU-Zeit benötigt, ich aber bei Änderungen insgesamt eine Stunde länger brauche, weil ich nach drei Monaten jedes Mal wieder genau überlegen muß, wie der reguläre Ausdruck eigentlich funktioniert, habe ich nichts gespart.
Wenn es aber wirklich auf Geschwindigkeit ankommt, ist eine Interpretersprache vielleicht nicht die erste Wahl.
wenn der Text zwischen den Suchtexten ähnlich wäre und sich durch einen
regulären Ausdruck ersetzen ließe, könntest Du die Funktion split benutzen.
Das ist gerade *kein* Fall fuer split().
Angenommen ich suche den Inhalt in einer HTML-Datei, dann nehme ich
@array = split (/<.*?>/, $text);
wenn ich die Tags suche, benutze ich
@array = split (/>[^<]*</, $text);
vielleicht ist die letztere Variante auch noch nach einer längeren Programmierpause besonders schnell zu verstehen- oder einfach nur Geschmackssache. Ist diese Variante denn von der Rechenzeit ungünstiger?
noch einen schönen Tag wünscht
Martin
Hi
1. Danke, die Möglichkeit die Suchergebnisse in einem Array zu bekommen habe ich gesucht.
perldoc perlfaq6, Abschnitt "Why does using $&, $`, or $' slow my program
down?".
Eine Frage gerade zu der Geschwindigkeit: Wie messt ihr die Geschwindigkeit eurer Programme, gerade wenn auf einem Server ausgeführt? Bei PHP sieht man das ja recht oft (gerade bei Foren uä.).
Andres Freund
Ps: Ich habe vor kurzem die Möglichkeit gesucht STDOUT in einen Skalar umzuleiten, es geht indem man ein Filehandle mit tie bindet, oder indem man IO::Skalar benutzt.