Thread Regex-Muster als Variable: Dezimalpunkt ersetzen (9 answers)
Opened by qwe123qwe at 2020-12-25 11:41

haj
 2020-12-25 17:57
#193036 #193036
User since
2015-01-07
558 Artikel
BenutzerIn

user image
2020-12-25T14:14:12 qwe123qwe
Vielen Dank !
Das ist genau das was ich gebraucht habe. Ich hab nicht gewußt, daß man so eine Trefferliste bekommt. Und genau danach hab ich gesucht.

Das freut mich.
In einem Punkt möchte ich trotzdem zurückrudern: Die Gefahr einer Endlosschleife, auf die ich hingewiesen habe, entsteht tatsächlich erst durch meine Zuweisung an @digits. Ohne diese Zuweisung liefert die while-Schleife jedes Mal einen neuen Treffer, wie gewünscht.

Du kannst aber die Menge aller Treffer auch erst innerhalb der Schleife retten, ohne jedesmal alle durchzählen zu müssen:
Code (perl): (dl )
1
2
3
while ($seite =~ /$muster/g) {
   # Hier gibt's keine Endlosschleife!
   my @digits = @{^CAPTURE}; # siehe perldoc perlvar

...und dann weiter wie bisher angegeben.

2020-12-25T14:14:12 qwe123qwe
Ich weiß, daß die Mustererkennung ziemlich hässlich aussieht, mit Regex steht ich auf Kriegsfuß. Aber ich bin schon froh, daß ich da überhaupt ein Muster hinbekommen habe, das funktioniert. Bin aber sehr offen für Verbesserungsvorschläge.

Ok, da gibt es zwei Ansätze:
  • Wenn Du einen regulären Ausdruck und nicht einfach einen String erzeugen willst, kannst Du anstelle der Anführungszeichen $muster="blabla" das Konstrukt $muster=qr/blabla/ verwenden. Innerhalb des Musters gilt dann die Syntax für reguläre Ausdrücke und nicht die für Strings, Du kannst also tatsächlich \d und \. schreiben, um nach einer Ziffer oder einem Punkt zu suchen.
  • Der x-Modifier für reguläre Ausdrücke erlaubt es, den gesamten Ausdruck in mehreren Zeilen zu schreiben, Leerzeichen und Kommentare sind möglich (um nach einem Leerzeichen zu suchen, muss man in dem Fall \s oder änliches benutzen):
    Code (perl): (dl )
    $muster = qr/bla bla/x

Nun also angewendet auf Deinen Ausdruck. Ob meine Variante funktioniert, musst Du selbst testen, ich habe ja Deine Testdaten nicht - Tipp- oder Verständnisfehler meinerseits will ich nicht ausschließen. In der ersten Stufe verwende ich einfach das qr/.../x-Konstrukt, ergänzt um Kommentare, wie ich Deine Regex interpretiere (das kann falsch sein). Ich selbst verwende gern Kommentare für Beispiele, was da gesucht wird, und insbesondere für die "Durchnummerierung" der ()-Konstruktionen.
Code (perl): (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
$muster = qr/(\d{2})\.(\d{2})\.(\d{2}) # 12.34.56  = $1,$2,$3
            .+?font-size-14.+?         # mittelalterliches HTML
            (   \d+\.\d+,\d+|          # 123.456,789 oder
                \d+\.\d+|              # 123.123 oder
                \d+,\d+|               # 123,123 oder
                \d+                    # 123
            )                          # = $4
            .+?font-size-14.+?         # mehr mittelalterliches HTML
            (   \d+\.\d+,\d+|          # 123.456,789 oder
                \d+\.\d+|              # 123.456 oder
                \d+,\d+|               # 123,456 oder
                \d+                    # 123
            )                          # = $5
            .+?font-size-14.+?         # wieder mittelalterliches HTML
            (   \d+\.\d+,\d+|          # 123.456,789 oder
                \d+\.\d+|              # 123.456 oder
                \d+,\d+|               # 123,456 oder
                \d+                    # 123
            )                          # = $6
            .+?font-size-14.+?         # nochmal mittelalterliches HTML
            (   \d+\.\d+,\d+|          # 123.456,789 oder
                \d+\.\d+|              # 123.456 oder
                \d+,\d+|               # 123,456 oder
                \d+                    # 123
            )                          # = $7
            .+?font-size-14.right.+?   # uff.  Bald geschafft.  right?
                                       # Obacht: Die letzte Gruppe ist anders.
            (   \d+\.\d+\.\d+|         # 123.123.123 oder
                \d+\.\d+|              # 123.123 oder
                \d+                    # 123
            )                          # = $8
            .+?right...                # right again...
            (\d+,\d+|\d+)              # 123,123 oder 123 = $9
            .+?(M|T)                   # weiter bis zum nächsten M oder T ($10)
            /x;

Die Einrückerei in den Klammern machen Editoren, die Perl verstehen (ich verwende Emacs mit CPerl mode) übrigens automatisch.

Als nächste Stufe erkenne ich, dass da wiederholte Sequenzen auftauchen, die man rausziehen kann. Damit haben wir:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
my $old_html = qr/.+?font-size-14.+?/;
my $ziffern  = qr/\d+\.\d+,\d+|          # 123.456,789 oder
                  \d+\.\d+|              # 123.123 oder
                  \d+,\d+|               # 123,123 oder
                  \d+                    # 123
                 /x;

$muster = qr/(\d{2})\.(\d{2})\.(\d{2}) # 12.34.56  = $1,$2,$3
            $old_html ($ziffern)       # = $4
            $old_html ($ziffern)       # = $5
            $old_html ($ziffern)       # = $6
            $old_html ($ziffern)       # = $7
            .+?font-size-14.right.+?   # uff.  Bald geschafft.  right?
                                       # Obacht: Die letzte Gruppe ist anders.
            (   \d+\.\d+\.\d+|         # 123.123.123 oder
                \d+\.\d+|              # 123.123 oder
                \d+                    # 123
            )                          # = $8
            .+?right...                # right again...
            (\d+,\d+|\d+)              # 123,123 oder 123 = $9
            .+?(M|T)                   # weiter bis zum nächsten M oder T ($10)
            /x;

In der Form finde ich sowas viel leichter lesbar als in einer einzigen Cinemascope-Zeile, zudem ist die Unterstützung durch die Editoren besser.

View full thread Regex-Muster als Variable: Dezimalpunkt ersetzen