![]() |
Regex Erläuterungen
Hallo,
mit TRegEx.IsMatch prüfe ich Inhalte auf Vorgaben von Datev. Bei der Rechnungsnummer ist die Vorgabe '^[a-zA-Z0-9$%&\*\+\-/]{1,36}$' Da kommt "keine Übereinstimmung" raus wenn z.B. "WZ 123456" oder "12.123.45678" in der Rechnungsnummer steht. Sehe ich das richtig, dass "a...z", "A...Z", "*", "+" und "-" erlaubt sind und die Länge 1-36 Zeichen sein muss? Was aber bedeutet "$%&" ? Danke Ciao Stefan |
AW: Regex Erläuterungen
Protipp:
Auch: Klar ist die zwischenmenschliche zärtliche Wärme hier in diesem Forum durch nichts zu toppen, aber grade solche Fragen sind eigentlich perfekt für x-beliebige KIs, welche auf deine Frage ausgespuckt hätte: Zitat:
|
AW: Regex Erläuterungen
Danke,
die Erklärung des Tools scheint sinnvoll, nicht aber der Regex den Datev vorgibt! Warum soll "a", "m" und "p" extra noch mal erlaubt sein, ist doch schon vorn bei "a...z" erlaubt? Ciao Stefan |
AW: Regex Erläuterungen
Zitat:
![]() |
AW: Regex Erläuterungen
Jupp, & sollte eigentlich ein & sein
und $% sind diese beiden Zeichen. Und ansonsten ist alles richtig. Da aber weder das Leerzeichen noch der Punkt erlaubt sind (nicht im Suchstring enthalten), können diese beiden Rechnungsnummern natürlich nicht getroffen werden. |
AW: Regex Erläuterungen
Vielen Dank, jetzt habe ich es begriffen!
Ciao Stefan |
AW: Regex Erläuterungen
Kleine Nachfrage:
Gibt es eine einfacvh Möglichkeit die falschen Zeichen, die nicht dem Muster entsprechen, herauszufiltern und dem Benutzer anzuzeigen (also z.B. '"." und " " sind nicht erlaubt"' Ciao Stefan |
AW: Regex Erläuterungen
![]()
Delphi-Quellcode:
'[^a-zA-Z0-9$%&*+\-\/]'
Delphi-Quellcode:
'[^a-zA-Z0-9$%&*+\-\/]+'
![]() ![]() |
AW: Regex Erläuterungen
Danke!
Es gibt mehrere Aufrufmöglichkeiten von Replace, irgendwie fehlen mir da Parameter... Kannst Du mit bitte mit 3 Zeilen Code weiterhelfen? Ciao Stefan |
AW: Regex Erläuterungen
Mein Ansatz läuft über Match-Groups (die Runden Klammern um den Ausdruck von himitsu). Damit bekommst du jedes einzelne Zeichen, das nicht deiner Vorgabe entspricht.
Delphi-Quellcode:
var res := TRegEx.Matches('12.123.45678', '([^a-zA-Z0-9$%&*+\-\/])');
for var i := 0 to res.Count - 1 do ShowMessage('nicht erlaubt: "' + res[i].Value + '"'); |
AW: Regex Erläuterungen
Danke,
das hilft schon mal weiter, wie bzw. wo aber setze ich die Klammern für die Negierung bei einer Expression mit Längenangabe wie '^[a-zA-Z0-9$%&;\*\+\-/]{1,36}$' Ich habe alle möglichen Varianten probiert, aber kein Erfolg! Ciao Stefan |
AW: Regex Erläuterungen
Längenangabe und Negierung sind für mich auf der ersten Blick logisch inkompatibel. Was möchtest du mit der Längenangabe denn erreichen?
|
AW: Regex Erläuterungen
Hast Recht, aber wenn ich die Längenangabe wegnehme funktioniert es nicht mehr, dann wird "0" als ungültiges Zeichen ausgegeben!
Liegt vielleicht am $ ganz hinten? Und noch viel schlimmer: Wie wandle ich denn so etwas um: '^[_a-zA-Z0-9\-]+(\.[_a-zA-Z0-9\-]+)*@([a-zA-Z0-9]+(\-[a-zA-Z0-9]+)*\.)+([a-zA-Z]{2,})$'; Ciao Stefan |
AW: Regex Erläuterungen
Welches konkrete Problem möchtest du denn mit der Längenangabe lösen? Kannst du da ein Beispiel nennen?
|
AW: Regex Erläuterungen
Code:
Findet "WZ 123456" sowohl auch "12.123.45678"
^[a-zA-Z0-9$%&\.\*\+\- \/]{1,36}$
|
AW: Regex Erläuterungen
Zitat:
Ich darf nicht auf das Gelände, weil da hängt ein Schile "Betreten verboten" .... egal, schraube ich einfach das Schild ab, dann darf ich drauf. Wobei ich nicht weiß, wie wir es machen (um die EDI kümmert sich wer Anderes) ... wir haben auch Punkte, Leerzeichen und sogar ' in Artikkelnummern drin. (Letzteres hatte viel Spaß im Python und auch darin erzeugtem SQL verursacht, bei den Übergaben zwischen Delphi<>Pythen<>SQL, als der erste Kunde auf diese geniale Idee gekommen war) |
AW: Regex Erläuterungen
Für die Rechnungsnummer:
* der Prüf-RegEx geht auf den kompletten String, von Anfang bis Ende (drum ^ und $ drumrum) * der der UngültigeZeichen-RegEx geht auf "ein" ungültiges Zeichen, oder eine Gruppe von Zeichen (wenn + , aber ihne ^ und $) * * zum Löschen oder ersetzen dieser Zeichen (ersetzen durch Leerstring oder ein gülties Ersatzzeichen, wie z.B. [delphi]-[delphi/]) Das geht hier, da die Prüfung an jeder Position die selben Zeichen erlaubt. TRegEx.Repleace: * erstmal überlegen, ob du Dieses als "Funktion" (Klassenmethode) ausführen willst, oder als Methode eines Objekts. * Wenn man es oft und schnell das Gleiche suchen oder ersetzen will, dann ist es mit dem Objekt eventuell optimaler, da der RegEx selbst nicht jedesmal neu initialisiert werden muß. (ich nutzte hier z.B. 3 RegEx-Instanzen, im OnCellPaint eines Grids, also sehr oft und schon etwas "zeitkrittisch") Zitat:
Bei so Kompliziertem ist es nicht so einfach eine Gegenprüfung zu basteln. Den RegEx selbst prüfen geht natürlich, um zu sagen "geht oder geht nicht", also alles zusammen. Rauszufilten was nicht geht, wird schwerer. Man könnte es so umbauen, dass die Teile optional aufbauend und nach hinten offen sind, dann liese sich zumindestens sagen "hier, bzw. ab hier geht es nicht". |
AW: Regex Erläuterungen
Zitat:
Sollte ich mich Irren, sind die Mustervorgaben von "sko1" Falsch (Illegal) bei Datev. |
AW: Regex Erläuterungen
Es gibt da einen zweiten RegEx in Post #13.
|
AW: Regex Erläuterungen
Zitat:
Und Ja, Du hast es richtig erkannt, es geht um Datev, wo ich bisher beim Export zu Datev dem Anwender angezeigt habe "ungültiger Inhalt" und das soll insofern erweitert werden, dem Anwender zu zeigen welche Zeichen da nicht erlaubt sind (und das für alle Felder, nicht nur die Rechnungsnummer)! Ciao Stefan |
AW: Regex Erläuterungen
"WZ 123456" oder "12.123.45678" sind dann Falsch, wenn Leerzeichen und Punkt ungültige Zeichen sind.
|
AW: Regex Erläuterungen
Dann brauche ich einen anderen Ansatz, um auch bei komplexen Vorgaben unerlaubte Zeichen zu finden:
Aus der Hilfe: Matches gibt alle Übereinstimmungen zurück, die im Input-String als eine TMatchCollection-Instanz vorhanden sind Also wollte ich mit der originalen Regex eine MatchCollection haben und deren Länge auswerten:
Delphi-Quellcode:
res.count aber ist immer = 0
var
res: TMatchcollection; begin // Pattern ist '^[a-zA-Z0-9$%&;\*\+\-/]{1,36}$' res := TRegEx.Matches(AttributInhalt, pattern); if res.count <> Length(Attributinhalt) then ... begin Irgendwas mache ich immer noch falsch :-( Ciao Stefan |
AW: Regex Erläuterungen
Irgendwie drehen wir uns aktuell etwas im Kreis.
Dein Pattern überprüft, ob dein Input exakt der Vorgabe entspricht. Wenn das nicht der Fall ist, dann ist das Ergebnis natürlich leer. Das "^" und "$" am Anfang und Ende des Pattern steht für den Anfang und das Ende deines Inputs. Wenn du die jedes Zeichen einzeln prüfen willst, dann könntest du das Pattern "[a-zA-Z0-9$%&;\*\+\-\/]" verwenden. |
AW: Regex Erläuterungen
Du hast schon Recht, ich dreh mich im Keis...
Ich muss doch nur unerlaubte Zeichen in einem String finden die nicht der vorgegebenen Expression entsprechen... Bei dem einfachen Beispiel kann ich die Expression ja negieren, wie aber bei solchen Konstrukten wie '^([A-Z]{4}[A-Z]{2}([A-Z0-9]){2}([A-Z0-9]){0,3})$' Ich hatte nun die Idee den zu untersuchenden Inhalt zeichenweise per Match zu testen bis keine Übereinstimmung mehr vorliegt also Zeichen 1 prüfen Zeichen 1..2 prüfen Zeichen 1..3 prüfen Zeichen 1..4 prüfen usw. aber auch da schlägt die Längenprüfung zu Deshalb der Ansatz per Matches in der Hoffnung, dass da aller erlaubten Zeichen enthalten sind (also ohne den Pattern zu negieren) nur funktioniert das so leider nicht! Es muss dafür doch irgendeine Lösung geben! Ciao Stefan |
AW: Regex Erläuterungen
Zitat:
|
AW: Regex Erläuterungen
[QUOTE=sko1;1544226]D
Delphi-Quellcode:
Wie ist AttributInhalt deklariert?
var
res: TMatchcollection; begin // Pattern ist '^[a-zA-Z0-9$%&;\*\+\-/]{1,36}$' res := TRegEx.Matches(AttributInhalt, pattern); if res.count <> Length(Attributinhalt) then ... begin Mit dem Pattern '^[a-zA-Z0-9$%&;\*\+\-/]{1,36}$' kannst du nur eine Zeile prüfen. Für einen größeren Text ist das Pattern Ungeeignet. z.B.:
Code:
PS.
'WZ123456'
'1211234542' // Ergebnis Pattern gefunden res = 2 'WZ123456 1211234542' // Ergebnis Pattern nicht gefunden res = 0 Pattern - '^[a-zA-Z0-9$%&;\*\+\-/]{1,36}$' sollte '^[a-zA-Z0-9$%&;\*\+\-\/]{1,36}$' so aussehen. Beim letzte Slash muß ein Backslsh vorran gestellt werden. |
AW: Regex Erläuterungen
[QUOTE=sko1;1544226]D
Delphi-Quellcode:
Wie ist AttributInhalt deklariert?
var
res: TMatchcollection; begin // Pattern ist '^[a-zA-Z0-9$%&;\*\+\-/]{1,36}$' res := TRegEx.Matches(AttributInhalt, pattern); if res.count <> Length(Attributinhalt) then ... begin Mit dem Pattern '^[a-zA-Z0-9$%&;\*\+\-/]{1,36}$' kannst du nur eine Zeile prüfen. Für einen größeren Text ist das Pattern Ungeeignet. z.B.:
Code:
'WZ123456'
'1211234542' // Ergebnis Pattern gefunden res = 2 'WZ123456 1211234542' // Ergebnis Pattern nicht gefunden res = 0 |
AW: Regex Erläuterungen
Hallo,
nach Tagen vergeblicher Versuche frage ich hoch mal anhand eines ganz konkreten Beispiels: Pattern = '^([A-Z]{2}\d\d([A-Za-z0-9]){11,30})$' Ich interpretiere das so; 2 Zeichen A...Z 2 Ziffern 11-36 Zeichen A...Za...z0...9 Damit sollte 'AA11abcdefghijkl' gültig sein? Als Input kommt aber z.B. 'AA11abcdefghij' dann sind alle Zeichen gültig, aber der letzte Teil zu kurz Als Input kommt aber z.B. 'Ax11abcdefghijkl' dann ist das zweite Zeichen falsch Wie macht man nun dem Anwender ersichtlich, wo er Eingabefehler hat? Ciao Stefan |
AW: Regex Erläuterungen
Du könntest nach einem fehlgeschlagenem RegEx noch die Abschnitte einzeln prüfen.
In etwa so (ungetestet):
Delphi-Quellcode:
function ValidateInputByPosition(Input: string): string;
var Match: TMatch; Errors: TStringList; LengthPart: Integer; begin Errors := TStringList.Create; try // Vollständige Musterprüfung if not TRegEx.IsMatch(Input, '^([A-Z]{2}\d{2}[A-Za-z0-9]{11,30})$') then begin // Abschnitt 1: Zwei Großbuchstaben if not TRegEx.IsMatch(Input, '^[A-Z]{2}') then Errors.Add('Die Eingabe muss mit zwei Großbuchstaben beginnen (z. B. ''AA'').'); // Abschnitt 2: Zwei Ziffern if not TRegEx.IsMatch(Input, '^[A-Z]{2}\d{2}') then Errors.Add('Nach den Großbuchstaben müssen zwei Ziffern folgen (z. B. ''11'').'); // Abschnitt 3: Länge des letzten Teils LengthPart := Length(Copy(Input, 5, MaxInt)); if LengthPart < 11 then Errors.Add(Format('Der letzte Teil muss mindestens 11 Zeichen lang sein, aber es sind nur %d Zeichen.', [LengthPart])) else if LengthPart > 30 then Errors.Add(Format('Der letzte Teil darf maximal 30 Zeichen lang sein, aber es sind %d Zeichen.', [LengthPart])); end; // Rückgabe if Errors.Count = 0 then Result := 'Die Eingabe ist gültig.' else Result := Errors.Text; finally Errors.Free; end; end; // Testaufruf procedure TestValidationByPosition; var Inputs: array[0..3] of string = ('AA11abcdefghijkl', 'AA11abcdefghij', 'Ax11abcdefghijkl', 'AA11abcdefghijklmnopqrstu'); I: Integer; begin for I := Low(Inputs) to High(Inputs) do Writeln(Format('Eingabe: %s', [Inputs[I]]), #13#10, ValidateInputByPosition(Inputs[I])); end; |
AW: Regex Erläuterungen
Danke für das Beispiel!
Ich habe allerdings ca. 20 verschiedene Patterns (DATEV Vorgaben) und wenn ich so wie in Deinem Beispiel vorgehe müsste ich für jedes einzelne dann so etwas zusammenbasteln... Gibt es da nicht irgendwas "allgemen verwndbares"?
Delphi-Quellcode:
Wenn Input länger als die ersten beiden Zeichen ist, wird IsMatch da schon Fehler werfen weil es mehr als 2 Zeichen für '^[A-Z]{2}' sind , oder?
// Abschnitt 1: Zwei Großbuchstaben
if not TRegEx.IsMatch(Input, '^[A-Z]{2}') then Errors.Add('Die Eingabe muss mit zwei Großbuchstaben beginnen (z. B. ''AA'').'); Ciao Stefan |
AW: Regex Erläuterungen
Es gibt die Named Matched Subexpressions, was aber Delphi meine ich nicht unterstützt.
![]() Zitat:
Das ist vielleicht je nach Implementierung verschieden. |
AW: Regex Erläuterungen
Bei aller Liebe
wäre es nicht einfacher 20 Prüfroutinen zu schreiben also 20 Regexen zu programmieren, vor allem da Regexen sich meist sehr schlecht überprüfen lassen, man versteht die ja in der Regel nicht wenn man sie anguckt, sondern nur in dem Moment wo man sie baut. Ich habe auch den Eindruck dass OP gar nicht so vertraut mit Regexen ist als dass er in einem Monat mit einem Blick auf eine Regex sagen könnte was diese Regex macht. |
AW: Regex Erläuterungen
Zitat:
Aber ja, alle Bedingungen separat in einer Routine oder sogar Klasse zu verpacken wäre sicher sauberer. Die kann sich dann in aller epischer Breite um EIN RegEx kümmern. |
AW: Regex Erläuterungen
Zitat:
|
AW: Regex Erläuterungen
Also ich denke es geht um die Teile innerhalb einer RegEx, wie z.B. in einer EMail:
Zitat:
Das meine ich, oder geht es doch um etwas Anders? |
AW: Regex Erläuterungen
Genau darum geht es...
Ciao Stefan |
AW: Regex Erläuterungen
Code:
Die Idee dahinter sind Non-capturing Groups (?: ) für die erlaubten Zeichen und Capturing Groups () für die nicht erlaubten mit einer Oder-Verknüpfung. Das bedeutet alles was in einer Capture Group landet ist ein falsches Zeichen. Die Zeilenumbrüche sind nur für die bessere Lesbarkeit hier im Forum.
^
(?:[A-Z]|(.)) (?:[A-Z]|(.)) (?:[0-9]|(.)) (?:[0-9]|(.)) (?:[A-Za-z0-9]|(.)){,12} $ |
AW: Regex Erläuterungen
Zitat:
Ich meine statt 20 Suchmuster (oder ein großes) in strings , plus einen Parser und einen Interpreter und oder Compiler für die suchmustersprache (Regex) in das Programm zu integrieren, wäre es nicht wesentlich productiver einfach die 20 Prüfroutinen in Pascal (das ist so eine imperative Programmiersprache mit eigentlich ziemlich guten String utilities) zu schreiben? Vor allem da OP Pascal anscheinend besser kann als Regexen. Ich denke Regexen sind eher sinnvoll wenn ein User oder ein Admin sie Konfigurieren kann! Also wenn ich z.b. den Filter oder Validator in einer Einstelldatei oder in der Software interaktiv festlegen möchte. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:10 Uhr. |
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-2025 by Thomas Breitkreuz