Font
[thread]6057[/thread]

Regex-Problem mit Backreferences



<< |< 1 2 3 4 5 >| >> 45 entries, 5 pages
DemoFreak
 2004-02-04 14:37
#79759 #79759
User since
2003-09-06
54 articles
BenutzerIn
[default_avatar]
Hallo zusammen,

ich habe ein kleines Problem mit einer RE, wo ich irgendwie nicht auf die Lösung komme. Gegeben sei eine Textdatei mit Zeilen, die so beginnen:

h040111.233001.gz bfb4e2e0-41f7-71d8-1c34-0aa0093f0000 cb32393c-5603-71d7-1bec-0aa01c1b0000 1 178260287 24 einrechner.einedomain.de 1 178260287 [...]

Die Zeilen enthalten also einige Strings definierter Länge (diese SID-artigen Teile), einige Zahlen und einige Strings variabler Länge, welchen eine Zahl, die ihre Länge ausdrückt, vorangestellt ist (bsplweise der Hostname). Um die Zeilen zu parsen, dachte ich mir, dass ich die Strings variabler Länge in der RE mit einem Konstrukt .{$length} bezeichne, und die Variable $length eine Backref auf das davorstehende Capture der Längenangabe ist. In Worten:

m/h(0401.+)\.gz [a-z0-9\-]{36} [a-z0-9\-]{36} \d+ \d+ (\d+) (.{$2}) .*/;

Das geht nicht. Weder, wenn ich $2 gegen \2 ersetze, noch wenn ich eine vorher "deklarierte" Variable statt der Backref verwende. Mit anderen Worten: wenn ich (?{ $anz=\2 }) hinter dem Ausdruck (\d+) einfüge, wird zwar meine Variable $anz korrekt auf den gecapturedten Wert gesetzt, aber ich kann nicht innerhalb der RE darauf zugreifen, sondern erst danach. Mit einem kleinen Progrämmchen sieht das so aus:

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

use strict;
#use warnings;
use re 'eval';

my $anz;

open XY, "<test.txt";
while (<XY>) {
   m/h(0401.+)\.gz [a-z0-9\-]{36} [a-z0-9\-]{36} \d+ \d+ (\d+) (?{ print "1. $2"; $anz=$2; print " $anz\n"}) (.{$anz})(?{ print "2. $2\n" }) .*/;
   print "3. $1 $2 $3\n";
}
close XY;


Die Ausgabe ist wie folgt:
hannes@asterix:~> ./testre.pl
1. 24 24
3.
1. 24 24
2. 24
3. 040112.233001 24 einrechner.einedomain.de

Wenn ich (.{$anz}) gegen (.{$2}) oder (.{$+}) austausche, wird selbst im zweiten Durchlauf der String nicht gecaptured, die Ausgabe ist dann so:

hannes@asterix:~> ./testre.pl
1. 24 24
3.
1. 24 24
3.

Wo ist hier mein Denkfehler? Kann man innerhalb einer RE nicht auf seine eigenen Captures zurückgreifen (wäre aber Unsinn, wozu sind sie denn sonst da), oder hab ich mich vertippt? Oder bin ich blond?

Please help! ;) ^^

Gruß, Hannes
Gruss, Hannes
Crian
 2004-02-04 14:48
#79760 #79760
User since
2003-08-04
5866 articles
ModeratorIn
[Homepage]
user image
Also $2 wird auf gar keinen Fall gehen, wenn Du im Suchteil schon auf gefangene Teile zugreifen willst, musst Du die Backslashvariante nehmen.

Ich schau mir gerade mal Dein Programm an und experimentiere herum ... warum willst Du
a) die Länge exakt angeben
b) nicht split statt der RE verwenden?

Quote
Kann man innerhalb einer RE nicht auf seine eigenen Captures zurückgreifen?


Doch, kann man, im Suchteil mit \1, \2, ... und danach (ggf. im Ersetzungsteil und im Anschluß) mit $1, $2, ...

Aber anscheinend kann man sie nicht einschrittig als Anzahl verwenden.\n\n

<!--EDIT|Crian|1075899795-->
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite
eisbeer
 2004-02-04 14:59
#79761 #79761
User since
2003-08-29
347 articles
BenutzerIn
[Homepage] [default_avatar]
[quote=Crian,04.02.2004, 13:48]... musst DU die Backslashvariante nehmen. ...[/quote]
Betonst du nicht das falsche Wort ;) ?

Ausserdem würd auch ich dir raten, vielleicht
was mit split zu versuchen ...
Die meisten PC Probleme befinden sich zwischen Bildschirm und Stuhl...
DemoFreak
 2004-02-04 15:00
#79762 #79762
User since
2003-09-06
54 articles
BenutzerIn
[default_avatar]
a) weil die Zeilen noch sehr viel länger sind und im hinteren Teil ab und zu leere Strings (Länge 0) bzw. Strings variabler Länge enthalten, die auch aus Leerzeichen und jeder Menge Sonderzeichen bestehen
b) weil ich (siehe a)) die Längenangabe verwenden muss ;)
Gruss, Hannes
Crian
 2004-02-04 15:02
#79763 #79763
User since
2003-08-04
5866 articles
ModeratorIn
[Homepage]
user image
Aber zweistufig gehts:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#!/usr/bin/perl
use strict;
use warnings;

my $anz;

while (<DATA>) {
   if ( m~h(0401[0-9.]+?)\.gz                   # -> $1
         \s
         [-a-z0-9]{36}
         \s
         [-a-z0-9]{36}
         \s
         \d+
         \s
         \d+
         \s
         (\d+)                                  # -> $2
         \s
         ~x
     )
   {
       print "3. $1 $2 ";
       m~h0401[0-9.]+?\.gz
         \s
         [-a-z0-9]{36}
         \s
         [-a-z0-9]{36}
         \s
         \d+
         \s
         \d+
         \s
         \d+
         \s
         (.{$2})                                # -> $1
         ~x;
       print "$1\n";
   }
   else {
       print "nö\n";
   }

}

_ _DATA_ _
h040111.233001.gz bfb4e2e0-41f7-71d8-1c34-0aa0093f0000 cb32393c-5603-71d7-1bec-0aa01c1b0000 1 178260287 24 einrechner.einedomain.de 1 178260287


Ausgabe:

Code: (dl )
3. 040111.233001 24 einrechner.einedomain.de
\n\n

<!--EDIT|Crian|1075900319-->
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite
DemoFreak
 2004-02-04 15:02
#79764 #79764
User since
2003-09-06
54 articles
BenutzerIn
[default_avatar]
Gut, wenn das scheinbar bei euch auch nicht geht, hat dann jemand eine andere Idee, wie ich das anders elegant "zerparsen" kann?

Wenn alle Stricke reißen, zerlege ich das halt an jedem String variabler Länge und mache es mit mehreren RE-Anweisungen, aber das kam mir uncool vor... ;)
Gruss, Hannes
Crian
 2004-02-04 15:05
#79765 #79765
User since
2003-08-04
5866 articles
ModeratorIn
[Homepage]
user image
[quote=eisbeer,04.02.2004, 13:59][quote=Crian,04.02.2004, 13:48]... musst DU die Backslashvariante nehmen. ...[/quote]
Betonst du nicht das falsche Wort ;) ?[/quote]
Tja... beim Schnelltippen schreibe ich bei großgeschriebenen Worten ganz oft zwei Buchstaben groß, und da ich das "Du" gern groß schreibe, sieht das da dann oft besonders komisch aus. ( Nach Betonung halt :-/ )

[quote=eisbeer,04.02.2004, 13:59]Ausserdem würd auch ich dir raten, vielleicht
was mit split zu versuchen ...[/quote]
Meine Rede ^^
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite
Crian
 2004-02-04 15:09
#79766 #79766
User since
2003-08-04
5866 articles
ModeratorIn
[Homepage]
user image
Variante mit Split:

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

while (<DATA>) {
my @parts = split;
#print "@parts";
(my $eins = $parts[0]) =~ s~^h(0401[0-9.]+?)\.gz$~$1~;
my $zwei = $parts[5];
my $drei = $parts[6];
print "3. $eins $zwei $drei\n";
}

_ _DATA_ _
h040111.233001.gz bfb4e2e0-41f7-71d8-1c34-0aa0093f0000 cb32393c-5603-71d7-1bec-0aa01c1b0000 1 178260287 24 einrechner.einedomain.de 1 178260287


Ausgabe:

Code: (dl )
3. 040111.233001 24 einrechner.einedomain.de


HTH
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite
DemoFreak
 2004-02-04 15:16
#79767 #79767
User since
2003-09-06
54 articles
BenutzerIn
[default_avatar]
[quote=DemoFreak,04.02.2004, 14:00]a) weil die Zeilen noch sehr viel länger sind und im hinteren Teil ab und zu leere Strings (Länge 0) bzw. Strings variabler Länge enthalten, die auch aus Leerzeichen und jeder Menge Sonderzeichen bestehen
b) weil ich (siehe a)) die Längenangabe verwenden muss ;)[/quote]
Split geht nicht. Es gibt kein Zeichen, an welchem man splitten könnte, denn weiter hinten in der Zeile gibt es Strings, die Leerzeichen enthalten bzw. von Länge 0 sind (d.h. dort stehen dann nach eine Ziffer 0 zwei Leerzeichen nacheinander). Berichtigt mich, wenn möglich ;)
Gruss, Hannes
renee
 2004-02-04 15:41
#79768 #79768
User since
2003-08-04
14371 articles
ModeratorIn
[Homepage] [default_avatar]
Benötigst Du denn "von weiter hinten" Informationen?? Ich nehme an, Du hast den gesamten relevanten Teil des Strings gepostet. Dann kann es einem relativ egal sein, ob dort noch Leerzeichen sind oder nicht!
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/
<< |< 1 2 3 4 5 >| >> 45 entries, 5 pages



View all threads created 2004-02-04 14:37.