Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   RegEx-Formatierung (https://www.delphipraxis.net/186176-regex-formatierung.html)

hansklok 10. Aug 2015 22:12

RegEx-Formatierung
 
Hallo ;)

Ich würde gern folgende Datumsangaben via RegEx splitten:
Delphi-Quellcode:
AUG 1917
2 AUG 1917
02 AUG 1917
1917B.C.
1917BC // wird nicht korrekt geparst
1917 B.C.
1917/18
1917/18 B.C.
ABT AUG 1917
INT 2 AUG 1917 (Mamas Geburtstag) // hier soll nur alles innerhalb der Klammer geparst werden, wobei Klammern und Inhalt ebenfalls optional sind
@#DGREGORIAN@ CAL 17 AUG 1917 // wird nicht korrekt geparst
@#DJULIAN@ 02 AUG 1917 // wird nicht korrekt geparst
@#DFRENCH R@ 02 VEND 1917 // wird nicht korrekt geparst
@#DHEBREW@ 02 TIS 5250 // wird nicht korrekt geparst
Bisher mache ich das so:
^(@#D(GREGORIAN|JULIAN|HEBREW|FRENCH\s*R)@)?\s*(AB T|EST|CAL|INT)?\s*(\d*)\s*([a-zA-Z]*)?\s*(\d*)?(\s*/)?(\d*)?\s*(BC|B.C.)?\s*(.*)?$

Das Parsen des Kalender Kalender funktioniert allerdings nicht richtig. Ich möchte nur, dass z.B. nur @#DHEBREW@ anstatt @#DHEBREW@ und HEBREW gemacht wird. Was muss ich abändern?

LG

idefix2 10. Aug 2015 23:53

AW: RegEx-Formatierung
 
Was meinst du mit "nur ... gemacht wird"?

hansklok 11. Aug 2015 00:17

AW: RegEx-Formatierung
 
Zitat:

Zitat von idefix2 (Beitrag 1311732)
Was meinst du mit "nur ... gemacht wird"?

Naja, jetzt gibt es sowohl ein Match, welches @#DHEBREW@ ausgibt und als zweiten Match eben DHEBREW. Ich möchte aber nur DHEBREW ausgegeben bekommen.

idefix2 11. Aug 2015 09:06

AW: RegEx-Formatierung
 
Normalerweise ist alles, was zwischen ( und ) steht, ein gefundener Unterausdruck, der in match[i] gemerkt wird. So viele Klammerpaare, soviele mögliche Unterausdrücke.
Lösung 1: Du merkst dir, welche Unterausdrucke dich interessieren (die Numerierung ist statisch, egal ob die Ausdrücke gefunden werden oder nicht). Alternativen müssen natürlich zwischen Klammern stehen, egal, ob du den entsprechenden Unterausdruck brauchst oder nicht.
Lösung 2: hängt von der Regex-Implementierung ab. Die meisten Implementierungen, die ich kenne, stellen eine Möglichkeit zur Verfügung, einen geklammerten Teil zu kennzeichnen, sodass der darin gefundene Inhalt nicht als Teilmatch registriert wird. Das müsstest du aber der Dokumentation deiner Regex-Implementierung entnehmen, weil das ist leider in der Sprache nicht genormt. Welche Regex-Routinen verwendest du?

hansklok 11. Aug 2015 11:09

AW: RegEx-Formatierung
 
@idefix2: ich nutze die "PCRE library". Das ist eine Perl kompatible Bibliothek.
Du sprichst von Untergruppen (Subgroups, oder). Davon habe ich gehört, verstehe aber deren Verwendung und Implementierung nicht.

idefix2 11. Aug 2015 11:53

AW: RegEx-Formatierung
 
In der Hilfe zu PCRE (Syntax specification) steht:

(?:...) non-capturing group

Code:
^(@#D(?:GREGORIAN|JULIAN|HEBREW|FRENCH\s*R)@)?\s*(AB T|EST|CAL|INT)?\s*(\d*)\s*([a-zA-Z]*)?\s*(\d*)?(\s*/)?(\d*)?\s*(BC|B.C.)?\s*(.*)?$
sollte also funktionieren

idefix2 11. Aug 2015 12:05

AW: RegEx-Formatierung
 
Was bei
1917BC // wird nicht korrekt geparst
nicht funktionieren soll, ist mir nicht klar.
Allerdings sind die Punkte beim B.C. problematisch, die musst du im Regex escapen, weil ein Punkt erkennt jedes beliebige Zeichen als gültig und es würde auch z.B. BIC7 als gültig erkannt werden.

also (BC|B\.C\.)

Zitat:

INT 2 AUG 1917 (Mamas Geburtstag) // hier soll nur alles innerhalb der Klammer geparst werden, wobei Klammern und Inhalt ebenfalls optional sind
Also was jetzt, willst du dass (ABT|EST|CAL|INT) gefunden wird oder nicht?

Nebenbei: Was soll
@#DFRENCH R@ 02 VEND 1917
sein? Vendredi ist doch ein Wochentag und kein Monatsname?

Noch was:
(\d*)? und (.*)?
Da ist das Fragezeichen unnötig, * bedeutet ja 0 mal oder öfter

hansklok 11. Aug 2015 20:30

AW: RegEx-Formatierung
 
Zitat:

Zitat von idefix2 (Beitrag 1311785)
Code:
^(@#D(?:GREGORIAN|JULIAN|HEBREW|FRENCH\s*R)@)?\s*(AB T|EST|CAL|INT)?\s*(\d*)\s*([a-zA-Z]*)?\s*(\d*)?(\s*/)?(\d*)?\s*(BC|B.C.)?\s*(.*)?$
sollte also funktionieren

Das funktioniniert schon mal hervorragend. Dankeschön dafür.
Zitat:

Zitat von idefix2 (Beitrag 1311789)
Was bei
Code:
1917BC // wird nicht korrekt geparst
nicht funktionieren soll, ist mir nicht klar. Allerdings sind die Punkte beim B.C. problematisch, die musst du im Regex escapen, weil ein Punkt erkennt jedes beliebige Zeichen als gültig und es würde auch z.B. BIC7 als gültig erkannt werden.
also (BC|B\.C\.)

So, das wird mittlerweile mittels folgendem String erkannt:
Code:
^(@#D(?:GREGORIAN|JULIAN|HEBREW|FRENCH\s*R)@)?(?:\s*)(ABT|EST|CAL|INT)?(?:\s*)(\d*)?(?:\s*)(JUN|AUG|VEND|TIS)?(?:\s*)(\d*)?(?:/)?(\d*)?(B\.C\.|BC)?$
Allerdings nach wie vor nicht die folgende Zeile:
Code:
1917/18 B.C.
Zitat:

INT 2 AUG 1917 (Mamas Geburtstag) // hier soll nur alles innerhalb der Klammer geparst werden, wobei Klammern und Inhalt ebenfalls optional sind.
Also was jetzt, willst du dass (ABT|EST|CAL|INT) gefunden wird oder nicht?
Also zur Erklärung des Datumseintrages der erkannt werden soll:

Kalendersystem (optional)
Wird keine dieser Angaben gefunden wird automatisch das Datum als Datum des gregorianischen Kalenders angenommen.
  • @#DGREGORIAN@
  • @#DJULIAN@
  • @#DHEBREW@
  • @#DFRENCH R@
Qualität (optional)
  • CAL (berechnetes Datum)
  • EST (geschätztes Datum)
Datum
  • Tag (optional)
  • Monat (optional, Monatsnamen abhängig vom Kalendersystem)
  • Jahr
    • duales Jahr (optional)
  • B.C./BC (optional, nur möglich, wenn Jahresangabe alleine ohne Tag und Monat notiert ist)
Datum als Freitext
  • INT (Tag) (Monat) Jahr (Freitext)
  • (Freitext)
Das ist also der Aufbau der Datumsnotation. Vielleicht hilft das beim Nachvollziehen.
Zitat:

Nebenbei: Was soll
@#DFRENCH R@ 02 VEND 1917
sein? Vendredi ist doch ein Wochentag und kein Monatsname?
Richtig, es ist Vendmaire (Monat des republikanischen Kalenders) gemeint ;)
Zitat:

Noch was:
(\d*)? und (.*)?
Da ist das Fragezeichen unnötig, * bedeutet ja 0 mal oder öfter
Das hast Du natürlich völlig recht. Ich arbeite mich grade erst in die regulären Ausdrücke ein.

idefix2 11. Aug 2015 22:17

AW: RegEx-Formatierung
 
Ich frage mich, ob es wirklich gescheit ist, ein derart aufwändiges Parsing mit einem einzigen Regex zu erschlagen, oder ob es nicht gescheiter wäre, die doch zum Teil grundverschiedenen Formate separat zu handhaben.

Eine Gruppe (?:\s*) zu bilden bringt gegenüber \s* keinen Vorteil. Ich würde per (?x) die erweiterte Syntax einschalten, dann kannst du im Regex Leerstellen zur besseren Lesbarkeit verwenden, Leerstellen werden dann für das Parsen ignoriert.

(\d*)?(?:/)?(\d*)?
ist nicht gut. Ich gehe davon aus, dass der Schrägstrich nicht allein auftreten darf, sondern nur als Trennung zwischen zwei Zahlengruppen (Jahreszahlen).
Also: (\d+/\d+|\d*)
Mit der 2. Alternative deckst du auch den Fall ab, dass das Jahr ganz weggelassen wird, es ist also auch nach dieser Gruppe kein ? nötig.

hansklok 11. Aug 2015 22:24

AW: RegEx-Formatierung
 
Zitat:

Zitat von idefix2 (Beitrag 1311874)
Eine Gruppe (?:\s*) zu bilden bringt gegenüber \s* keinen Vorteil. Ich würde per (?x) die erweiterte Syntax einschalten, dann kannst du im Regex Leerstellen zur besseren Lesbarkeit verwenden, Leerstellen werden dann für das Parsen ignoriert.

OK, und wie genau gehe ich da jetzt vor? Step by Step? Leuchtet meine Erklärung zum Aufbau des Datums ein?


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:12 Uhr.
Seite 1 von 3  1 23      

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