Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Verständnissfrage: Reguläre Ausdrücke (https://www.delphipraxis.net/166170-verstaendnissfrage-regulaere-ausdruecke.html)

Andreas2k 1. Feb 2012 16:40

Verständnissfrage: Reguläre Ausdrücke
 
Hallo,
Reguläre Ausdrücke bereiten mir immer noch Probleme beim Verständnis.

Beispiel Rückwärtsreferenzen

Ich habe folgenden Quellstring

<h1 class="test" id="29">

Möchte ich jetzt nur die Zahl von id haben, habe ich durch Zufall herausgefunden das es hiermit geht

(['"]?)(\d+)\1(\d+)\1

(zum Testen habe ich RexExp Studio genommen)

mit (['"]?)(\d+)\1(\d+)\1 findet er exakt 29 (ohne ")
markiert wird <h1 class="test" id="29">

wie gesagt ich habe das nur durch Zufall herausgefunden der Original Ausdruck sah so aus
(['"]?)(\d+)\1
und hat folgendes markiert ("29" Zahl samt Anführungszeichen)
<h1 class="test" id="29">

Ich würde gern verstehen warum mein Zufallstreffer funktioniert und nur die Zahl (ohne Anführungszeichen) markiert.

Soweit ich verstanden habe steht \1 für den Fund aus der ersten Gruppe also demnach "
(['"]?)(\d+)\1 würde also für "29" stehen

Warum bewirkt jetzt aber dieser Teil (['"]?)(\d+)\1(\d+)\1 das nur die Zahl in der Mitte markiert wird? Oder ist das ein Bug?

Bernhard Geyer 1. Feb 2012 16:45

AW: Verständnissfrage: Reguläre Ausdrücke
 
Hast du wirklich HTML-Code vor dir?
Da würde ich einen HTML nehmen anstatt das mit Regex zu versuchen.

Phoenix 1. Feb 2012 17:46

AW: Verständnissfrage: Reguläre Ausdrücke
 
Also die Regex
Code:
(?<firstGroup>['"]?)(?<secondGroup>\d+)
Matched bei der Eingabe von '<h1 class="test" id="29">' folgendes:
Code:
[1]
  firstGroup: []
  secondGroup: [1]
["29]
  firstGroup: ["]
  secondGroup: [29]
Wie Du siehst, matched er also sogar das 1 von <h1 mit, weil Du die Hochkommas in ['"]? mit dem ? als Optional markiert hast. Ich habe hier die Backreference mal weggelassen, und so siehst Du dass nur "29 gematched wurde.

Durch das Hinzufügen der Backreference \1 an den Ausdruck wird die erste Gruppe (['"]?), also das optionale " oder ', wieder verwendet. Das ist das gleiche wie wenn Du
(['"]?)(\d+)(['"]?) schreiben würdest. Damit wird dann auch "29" gematched.

Schauen wir uns nun Deinen Zufallstreffer an:
Code:
(['"]?)(\d+)\1(\d+)\1
auflösen der Backreferenzen ==> (['"]?)(\d+)(['"]?)(\d+)(['"]?) Achtung: nicht GANZ korrekt! Siehe unten!
Der eigentliche Match sind die zwei (\d+) getrennt von einem optionalen Hochkomma:
Code:
[29]
1: []
2: [2]
3: [9]
und zwar nur, weil Du Backreferences verwendet hast.

Da die Backreferenz treffen muss, Deine Regex matched also nur, wenn ALLE optionalen Hochkommas vorhanden wären, also z.B. "2"9".
Was also gematched wird sind belibig viele Ziffern getrennt von einem Hochkomma, wenn die erste Gruppe eines findet und NICHT getrennt von einem Hochkomma, wenn die erste Gruppe keines findet.

Anderer Input: id="269" Match:
Code:
[269]
1: []
2: [26]
3: [9]
Wie Du siehst matched die Gruppe zwei erstmal so viel sie kann (Greedy) und erwischt die 26, die erste Gruppe matched nicht weil kein Hochkomma die dritter Gruppe (die andere (\d+)) abtrennt.

Deswegen bekommst Du auch die Hochkommas nicht mit.

Du hast also tatsächlich nur einen Zufallstreffer, eine einstellige ID würdest Du damit nämlich nie finden.

Was Du eigentlich willst ist
Code:
=(['"]?)(\d+)\1
und von diesem Match nimmst Du nur den Wert aus der zweiten Gruppe.
Das = ist noch drin damit das 1 von h1 nicht mit gematched wird, sondern nur id="12" id='12' oder id=12.

Andreas2k 2. Feb 2012 10:35

AW: Verständnissfrage: Reguläre Ausdrücke
 
Vielen Dank für die ausführliche Erklärung. Ich glaube jetzt habe ich es so einigermaßen verstanden:wink:


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:14 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz