Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]7612[/thread]

Referenzierung von Teilmustern dynamisch ausgeben: Referenzierungs variable dynmaisch setze

Leser: 2


<< |< 1 2 >| >> 19 Einträge, 2 Seiten
eisbaermann
 2006-01-12 11:29
#61724 #61724
User since
2006-01-12
3 Artikel
BenutzerIn
[default_avatar]
Schönen guten Tag,

im Augenblick bin ich an der Programmierung eines kleinen Statistik-Programms, dass persönliche Logfiles auswerten soll.

Die Logs werden auf bestimmte Muster hin untersucht und Teilmuster ausgegeben.

Da die ganzen Expressions stätig anwachsen und ich jedes mal den Code verändern muss, habe ich mir überlegt, das ganze etwas einfacher zu machen.

Mir kam die Idee das ganze erstmal durch ein Array zu realisieren.
Beispiel:
Code: (dl )
1
2
my %testar = ();
$testar{ 'reg1' } = { 'exp' => '\\/var\\/logs\\/logger\\/(\d*)\\/(\d*)', 'desc' => 2 };

'desc' gibt dabei an, welches Teilmuster eine besondere Bedeutung hat.
Es kann also auch vorkommen, dass ein Muster über 2 oder mehr Teilmuster verfügt.
Wichtig wäre immer das Teilmuster mit Nummer aus 'desc' zu erhalten.

Ich müsste also in der obigen TestExp das Teilmuster 2 erhalten.
Code: (dl )
print ("${ $testar{ 'reg1' }{ 'desc' } }\n");

würde bei deaktiviertem strict auch funktionieren. Das gefundene Teilmuster $2 wird ausgegeben.

Mit strict gibt es die üblichen Referenzierungsprobleme:
"Can' t use string as a SCALAR"

Für mich macht es nur wenig Sinn auf Grund dieses Problems strict abzuschalten.

Gibt es also eine saubere Möglichkeit die Variable zu expandieren?

Leider hatte ich bisher nur diese Idee, wenn jemand eine bessere Lösung wüsste, dann nur her damit.

Vielen Dank.
bloonix
 2006-01-12 12:15
#61725 #61725
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
[quote=eisbaermann,12.01.2006, 10:29]Für mich macht es nur wenig Sinn auf Grund dieses Problems strict abzuschalten.[/quote]

ach wo... es geht auch mit einem neuen Geltungsbereich
und "no strict 'refs';" :)

[quote=eisbaermann,12.01.2006, 10:29]
Gibt es also eine saubere Möglichkeit die Variable zu expandieren?[/quote]

ich hätte da zwei Möglichkeiten für dich ...

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/perl -w
use strict;

# ein Teststring
my $string = "dies ist ein test";

# nummerierte Variable, die du ausgeben oder zwischenspeichern moechtest
my $desc = 2;

my @ausgabe = ($string =~ /^(dies) (ist) (ein) (test)$/);

# kurz strict 'refs' deaktivieren in einem eigenen Geltungsbereich
{ no strict 'refs'; print "${$desc}\n"; }

# Da Arrays mit 0 beginnen, musst du bei $desc minus 1 rechnen.
print "$ausgabe[--$desc]\n";


Also entweder kannst du mit no strict oder mit einem Array
arbeiten.\n\n

<!--EDIT|opi|1137064622-->
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
renee
 2006-01-12 12:15
#61726 #61726
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Du kannst ja auch in einem kleinen Scope use strict ausschalten. Beim Verlassen des Scopes ist strict dann wieder an...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
eisbaermann
 2006-01-12 13:02
#61727 #61727
User since
2006-01-12
3 Artikel
BenutzerIn
[default_avatar]
@opi: vielen dank für Deine Hinweise.

Die Idee mit dem Array halte ich für die effizientere, da ich so gleich zwei Fliegen mit einer Klappe erschlage:
1. Ich habe alle Teilmuster gespeichert und kann diese, falls erforderlich, weiter verarbeiten.
2. ich muss strict nicht abschalten und kann dennoch auf den richtigen Wert zugreifen.

Tja, manchmal sieht man den Wald vor lauter Bäumen nicht...

Vielen Dank.
bloonix
 2006-01-12 13:15
#61728 #61728
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
[quote=eisbaermann,12.01.2006, 12:02]Die Idee mit dem Array halte ich für die effizientere[/quote]

Das ist sie aber nicht. Die Teilstrings sind schon in den
nummerierten Variablen abgelegt und werden zusätzlich ins
Array gepackt. Effizienter wäre es, mit "no strict 'refs';" zu
arbeiten.

[quote=eisbaermann,12.01.2006, 12:02]
1. Ich habe alle Teilmuster gespeichert und kann diese, falls erforderlich, weiter verarbeiten.
2. ich muss strict nicht abschalten und kann dennoch auf den richtigen Wert zugreifen.[/quote]

Ok, dass sind zwei Gründe für den Einsatz des Arrays.

Aber dann solltest du die 'desc'-Werte so setzen, dass sie in
der Zählung mit 0 beginnen, damit du direkt auf den richtigen
Index zugreifst und nicht erst minus 1 rechnen musst.
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
Strat
 2006-01-12 13:45
#61729 #61729
User since
2003-08-04
5246 Artikel
ModeratorIn
[Homepage] [default_avatar]
Irgendwie habe ich das gefuehl, ihr doktort an der voellig falschen stelle herum...

Regulaere Ausdruecke sollte man lieber nicht als string angeben, sondern als regulaeren ausdruck:
Code: (dl )
1
2
3
4
$testar{ 'reg1' } = { 
'exp' => qr~\Q/var/logs/logger/\E(\d*)/(\d*)~,
'desc' => 2,
};

das \Q....\E sagt aus, dass dort irgendwelche Zeichen, die fuer eine Regex Sonderzeichen sind, gequotet werden; sonst kann die verwendung probleme bereiten (z.B. oeffnende Klammern, +, *, ...)

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/perl
use strict;

# besser aus -w, weil es nur auf den aktuellen scope geht;
# hier ist der scope die komplette datei.
# es gibt naemlich immer noch einige Module, die bei -w (globale warnungen an) warnungen
# produzieren; deshalb besser use warnings verwenden...
use warnings;

# nummerierte Variable, die du ausgeben oder zwischenspeichern moechtest
my $desc = 2;
...

# wofuer braucht man hier das no strict? und das ${$desc} ???
# Das gibt den dereferenzierten wert von $desc zurueck, und $desc ist eine
# zahl, keine referenz => ergo sinnlos
{ no strict 'refs'; print "${$desc}\n"; }


1. Loesungsansatz: vermutlich unnoetig kompliziert, aber falls 2. nicht in frage kommt...
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
my %testar = (
'reg1' => {
'exp' => qr~\Q/var/logs/logger/\E(\d*)/(\d*)~,
'desc' => 2,
},
'req2' => {
'exp' => qr~...~,
'desc' => 1,
},
);

# entweder ueber ein explizites array:
my @fields = $string =~ $testar{req1}->{exp};
my $wantedField = @fields[ $testar{req1}->{desc} - 1 ];

# oder kuerzer, ohne das explizite array
my $wantedField = ( $string =~ $testar{req1}->{exp} )[ $testar{req1}->{desc} -1 ];


2. Loesungsansatz:
aber diese loesung ist immer noch viel zu kompliziert; wenn du nur ein einziges feld haben willst und dich der rest nicht interessiert, warum capturest du es dann? Mit (?:\d*) kannst du nicht einfangende klammern schreiben; dann kannst du auf das desc verzichten, auf den arrayindex -1 und vielleicht auch auf eine ebene, z.B.
Code: (dl )
1
2
3
4
5
my %testar = (
'reg1' => qr~\Q/var/logs/logger/\E(?:\d*)/(\d*)~,
'req2' => qr~...~,
);
my ($wantedField) = $string =~ $testar{'req1'};

(wobei man in diesem fall (?:\d*) auch einfach durch \d* ersetzen koennte...)

wenn man ueberlegt, no strict zu verwenden, ist man in 95% der faelle auf dem falschen weg, und handelt sich nur mehr probleme ein als man damit loest.\n\n

<!--EDIT|Strat|1137066483-->
perl -le "s::*erlco'unaty.'.dk':e,y;*kn:ai;penmic;;print"
http://www.fabiani.net/
sesth
 2006-01-12 13:58
#61730 #61730
User since
2005-02-01
181 Artikel
BenutzerIn
[default_avatar]
Entweder verstehe ich die vorgeschlagenen Lösungen nicht oder es ist wirklich nur ein Referenzierungsproblem.
Code: (dl )
print (" $testar{ 'reg1' }{ 'desc' } \n");

sollte einwandfrei laufen.
Gruß
Thomas
bloonix
 2006-01-12 13:59
#61731 #61731
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
[quote=Strat,12.01.2006, 12:45]besser aus -w, weil es nur auf den aktuellen scope geht;
hier ist der scope die komplette datei.
es gibt naemlich immer noch einige Module, die bei -w
[/quote]

Gerade darum ... Module, die warnings produzieren werden von
mir nicht verwendet. Entweder gibt es eine neuere Version, wo
diese Warnung nicht mehr vorkommt oder es fällt weg.

Wenn das Modul wichtig für mich ist, dann gibt es andere
Möglichkeiten.

[quote=Strat,12.01.2006, 12:45]
wofuer braucht man hier das no strict? und das ${$desc} ???
[/quote]

Can't use string ("2") as a SCALAR ref while "strict refs" in use at ...

[quote=Strat,12.01.2006, 12:45]
wenn man ueberlegt, no strict zu verwenden, ist man in 95% der faelle auf dem falschen weg, und handelt sich nur mehr probleme ein als man damit loest.[/quote]

deshalb auch mein zweiter Vorschlag mit dem Array.
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
eisbaermann
 2006-01-12 14:27
#61732 #61732
User since
2006-01-12
3 Artikel
BenutzerIn
[default_avatar]
@strat: bei der Verwendung soll das Skript zumeist das Teilmuster aus 'desc' matchen.
Allen anderen Teilmuster sollen aber für eine spätere Statistik verwendet werden können, sonst wäre ich nicht auf meine absonderliche Idee gekommen.

@sesth:
ja, laufen wird das ganze, wie ich bereits erwähnt habe schon, aber dann verwendest Du entweder kein "use strict" oder Du hast die scope-lösung verwendet.

@opi: vielen Dank für Deine Vorschläge. Ich habe die Lösung mit dem array gerade in meinen Code mit eingebaut. Läuft wie erwartet.
sesth
 2006-01-12 14:44
#61733 #61733
User since
2005-02-01
181 Artikel
BenutzerIn
[default_avatar]
[quote=eisbaermann,12.01.2006, 13:27]@sesth:
ja, laufen wird das ganze, wie ich bereits erwähnt habe schon, aber dann verwendest Du entweder kein "use strict" oder Du hast die scope-lösung verwendet.[/quote]
Da komme ich immer noch nicht mit.
Code (perl): (dl )
1
2
3
my %testar = ();
$testar{ 'reg1' } = { 'exp' => '\\/var\\/logs\\/logger\\/(\d*)\\/(\d*)', 'desc' => 2 };
print (" $testar{ 'reg1' }{ 'desc' } \n");

läuft mit use strict einwandfrei.

Code (perl): (dl )
print (" ${$testar{ 'reg1' }{ 'desc' }} \n");

wirft zurecht den Fehler, da Du versuchst, '2' zu dereferenzieren.
Gruß
Thomas
<< |< 1 2 >| >> 19 Einträge, 2 Seiten



View all threads created 2006-01-12 11:29.