Schrift
[thread]9086[/thread]

Precompiled Regex - no $1, $2, $3, ... ?



<< >> 3 Einträge, 1 Seite
Gast Gast
 2007-06-14 01:43
#77518 #77518
hey, wollt ein prog von mir beschleunigen, indem ich häufig verwendete regex procompile, möchte also quasi folgendes:

Code: (dl )
1
2
3
4
5
6
7
my $Count = 1000;
while ($Count--){
my $TimeString = 'Die ist nicht <b>so toll</b> oder?';
if( $TimeString =~ /\>([^\<]*)\</ ){
print "$1\n";
}
}


in folgendes umwandeln:

Code: (dl )
1
2
3
4
5
6
7
8
my $Count = 1000;
my $regex = /\>([^\<]*)\</;
while ($Count--){
my $TimeString = 'Die ist nicht <b>so toll</b> oder?';
if( $TimeString =~ $regex ){
print "$1\n";
}
}



an sich wird das zuvor compilete regex schon als solches erkannt, doch kann ich beim 2. beispiel nichtmehr mit $1 oder $2 auf die gefundenen (geklammerten) werte zugreifen wie beim ersten beispiel. gibts ne möglichkeit, precompilte regexs zu verwendet, ohne auf die "Fund-variablen" wie $&, $1, $2, ... verzichten zu müssen?
Dubu
 2007-06-14 02:32
#77519 #77519
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
Es muss
my $regex = qr/\>([^\<]*)\</;
heißen. Oder einfacher:
my $regex = qr/>([^<]*)</;

(s. perlop, Quote and Quote-like Operators)\n\n

<!--EDIT|Dubu|1181774212-->
sid burn
 2007-06-14 02:38
#77520 #77520
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
1) In diesem Beispiel brauchst du keine precompiled Regex.
Wenn du in deinem Code soetwas fest stehen hast.

Code: (dl )
if ( my $line =~ m/.../ ) { ... }


dann wird die Regex für den Match schon nur einmalig beim Start des Programmes Compiliert. Die Regex wird nicht ständig neu Compiliert wenn du auf den if blockt kommst.

Perl ist doch keine Interpreter Sprache. ;) (Oder Python das nur maximal 20 Regex Kompilationen im Speicher bereit hält, und wenn du 21 Regex in einer Schleife hast immer wieder absolut jede Regex bei jedem Durchlauf neu Compiliert wird. *g* )

Ansonsten würdest du das Programm sogar etwas verlangsamen wenn du an dieser Stelle eine Precompiled Regex benutzt. Da die Variable immer wieder erstmal zumindest gelesen werden muss. (Könnte sich ja in der Zwischenzeit verändert haben)

2)
Precompiled Regex nutzt du nur dann wenn du Variablen in einer Regex einfügst und diese Variable als Regex interpretiert werden soll. Variablen werden nämlich in einer Regex immer erst dann ausgewertet wenn die Regex engine auf die variable trifft. Und dann muss die Variable als Regex neu Compiliert werden, dieses neu Kompilieren ersparst du dir dann. Aber das hast du in deinem Beispiel ja nicht.

Hier ein kleiner Anwendungsfall

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
my @regexes = (
qr/regex1/,
qr/regex2/,
qr/regex3/,
);

while ( my $line = <> ) {
for my $regex ( @regexes ) {
if ( $line =~ m/$regex/ ) {
print "Foo\n";
}
}
}


Wenn man normale Variablen nutzen würde, dann würde es für jede Zeile in der Datei drei Regex Kompilierungen geben. So gibt es nur drei Regex Kompilierungen beim Programm start. Allerdiengs entsteht trotzdem etwas mehr Overhead als wenn du die Regex direkt hineinschreiben würdest da $regex immer wieder neu gelesen werden muss.

Dafür hast du den Vorteil das dein Programm Kompakter und leichter erweiterbar ist.

Die Schnellste Möglichkeit wäre, wenn du alle drei Regexe in der while mit drei if() shcleifen überprüfen würdest.

Das schnellste + kompakteste wäre wenn du dir einen String zusammenbaust der dann die drei if anweisungen enthält, und du diesen dann mit String eval ausführst. Allerdiengs ist diese Methode nur dann am schnellsten wenn die Laufzeit größer ist als das ausführun eines einmaligen evals. Sprich du brauchst verdammte viele Zeilen bis diese Methode schneller wird. Zusätzlich ist das aber auch die am schwerst verständlichste Methode, und am schlechtesten Lesbar. Daher würde ich davon abraten!

3)
Warum sollte $1 etc. nicht gehen? Dieses kleine Programm gibt mir erfolgreich "10" aus.

Code: (dl )
1
2
3
4
5
6
7
8
9
#!/usr/bin/perl
use warnings;
use strict;

my $regex_number = qr/(\d+)/;

if ( "Hallo 10 Welt" =~ m/$regex_number/ ) {
print $1, "\n";
}


$&, $`, $' sollte man NIE benutzen!\n\n

<!--EDIT|sid burn|1181774586-->
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
<< >> 3 Einträge, 1 Seite



View all threads created 2007-06-14 01:43.