Nun scheitere ich aber schon am Pattern für die Erste Zahl im String.
Ich finde nur Lösungen mit Gruppen, wie: pattern = @"^[\D]*(\d+)"
Das findet aber auch im ersten Beispiel X001, was natürlich nicht funktioniert.
Ja, diese Seite habe ich auch genutzt und habe mit dem Pattern wie oben beschrieben ein Match "X001" und eine Group "001".
Ich möchte aber nur die Zahl haben.
ein Match "X001" und eine Group "001".
Ich möchte aber nur die Zahl haben.
Ich kenne es von einigen Sprachen so, dass dort Match und Search unterschieden wird, wobei Match immer den gesamten String matchen muss, Search dagegen matches von Teilstrings sucht und findet.
Aber selbst wenn es ein Search in deiner unbekannten Umgebung nicht gibt: Warum nutzt du nicht den match der Group?
Ansonsten hilft vielleicht ein non-greedy skip (".*?")?
Ich nutze C#.
Danke für den Input (Submatches, Search, non-greedy), ich werde mich da mal einlesen.
Am Ende müssen halt alle Patterns mit dem selben Code funktionieren.
Mit try{} catch{} fange ich fehlerhafte Patterns vom User ab. Dann passiert halt einfach gar nichts.
Ja, das ist mir auch schon aufgefallen.
Anscheinend kann man in .NET diese Modifikatoren aber nur als Parameter übergeben und nicht mit im Pattern einbauen. Dann wäre das in der Tat eine gute Lösung.
\d+ alleine soll ja auch schon alle Nummern matchen.
Das Problem ist, dass Lookbehind keine dynamischen Pattern erlaubt.
Lookahead kann das, und das nutze ich dann so für die letzte Nummer im String:
\d+(?!.\d)
Für die erste Nummer wäre das entsprechend:
(?<!\d.)\d+
Das geht aber nicht, weil Das Lookbehind Pattern durch das "*" dynamisch wird.
Also bleiben nur noch kompliziertere Pattern mit Gruppen, die aber spezifische Outputs generieren welche ich nicht generisch auswerten kann.
Es muss aber generisch bleiben, da ja auch alle anderen oben genannten Kriterien funktionieren müssen.
Und darüber hinaus alle möglichen anwendugsspezifischen Pattern der User.
Meine Lösung ist nun wie folgt.
Es sind nur Patterns ohne Gruppen erlaubt
Dafür gibt es eine weitere Variable "max" mit der Anzahl der Matches die maximal ersetzt werden sollen
Der Code dazu schaut dann so aus:
1
Regex reg = new Regex(pattern);
2
string result = reg.Replace(input, delegate (Match m) {
Ja. Sowas programmiert man selbst. Mit RegEx suchst du dir den Wolf in der Doku und musst dauernd ausprobieren. Spätestens nach einer Woche, hast du den kryptischen Kram größtensteils wieder vergessen.
Für sowas nehme ich gerne Pascal und Structorizer für die Nassi-Shneiderman Diagramme. Änderung im Diagramm verändert Code und umgekehrt. Das geht ratzfatz und du blickst auch noch nach Jahren durch, kannst es sogar in andere Sprachen übersetzen. Da kommt RegEx nicht mit.
Verstehe ich nicht.
Soll ich nun eine eigene RegEx Syntax für meine User designen und die passende Engine dafür aus Nassi-Shneiderman Diagrammen generieren lassen?
Ich gebe dir ja in soweit Recht, dass ich RegEx jedes Mal wenn ich es benötige vorher erneut lernen muss, weil ich den kryptischen Kram nach spätestens einer Woche größtenteils wieder vergessen habe.
Aber RegEx ist standardisiert und in jeder Sprache verfügbar.
Soll ich nun eine eigene RegEx Syntax für meine User designen
Nö, das ist eher keine gute Idee, außer Du machst es aus Spaß am Syntax-Design und Doku dafür schreiben; vor allem letzteres ist dabei ein nicht zu unterschätzender Aufwand und wird trotzdem zwangsläufig mickrig bleiben im Vergleich zur bereits online Verfügbaren Breite an Doku zu .NET RegEx.
Was Du aber ggf. machen könntest, wäre den passenden syntactic-sugar für Deine konkrete Anwendung zu schaffen um z.B. Deinen max-Parameter direkt in die RegEx schreiben zu können.
Wenn dem wirklich so wäre, dann bräuchte regex101.com wohl kaum 8
Flavours zur Auswahl anbieten, oder?
Vermutlich weil es 8 Standards gibt ;)
Was Du aber ggf. machen könntest, wäre den passenden syntactic-sugar für
Deine konkrete Anwendung zu schaffen um z.B. Deinen max-Parameter direkt
in die RegEx schreiben zu können.
Hatte ich auch kurz drüber nachgedacht und schnell wieder verworfen.
Ich möchte nicht den 9ten Standard schaffen... ;)
Mit der aktuellen Lösung bin ich sehr zufrieden.
So wie Screenshot ist es voreingestellt.
Der versierte User kann das beliebig anpassen.
Die aktive Methode wird dann per Drop-Down im Ribbon ausgewählt.
Für die erste Nummer wäre das entsprechend:
(?<!\d.*)\d+
Das geht aber nicht,
Hmm... also auf regex101.com funktioniert das bestens.
weil Das Lookbehind Pattern durch das "*" dynamisch wird.
In der von Dir verlinkten Doku finde ich keinen Hinweis darauf, daß es für Lookbehind-Pattern andere Einschränkungen als für Lookahead-Pattern geben würde; im Gegenteil, in allen vier Varianten findet sich die Aussage:
1
Here, subexpression is any regular expression pattern.
Bei meinen eigenen Versuchen habe ich erstmal folgendes Pattern gebastelt, das wunderbar geklappt hat:
1
(?<=^\D*)\d+
Erst dann ist mir aufgefallen, daß hier ebenfalls der * im Lookbehind-Pattern vorkommt, was lt. Deiner Aussage nicht sein dürfte.
Jedenfalls liefern beide Pattern bei jedem Deiner vier Teststrings jeweils die erste Zahl als einzigen Match; zumindest auf regex101.com
Wenn dem wirklich so wäre, dann bräuchte regex101.com wohl kaum 8
Flavours zur Auswahl anbieten, oder?
Vermutlich weil es 8 Standards gibt
Mehr sogar. Ich weiß gar nicht, wie oft wir schon mit unserem Projekleiter darüber diskutieren mussten.
Ganz ätzend sind regex patterns in OpenApi Schemata, wenn z.B. eine Java EE Anwendung Dienste bereit stellt, die fünf andere Sprachen/Frameworks konsumieren, mit drei Test Tools manuell aufgerufen werden und ein Swagger Validator via Ci/Cd Pipeline überprüft. Ein herrliches Chaos ist das.
Dann diskutiere mal mit dem Projektleiter darüber, welches Pattern nun das "offizielle" für Email Adressen sein soll. Oder für Benutzernamen mit Unicode.
Hmm... also auf regex101.com funktioniert das bestens.
Oh mann... das ist jetzt natürlich peinlich.
Bei all meinen Versuchen auf regex101 bin ich nie auf die Idee gekommen den Flavor umstellen.
Und in der Tat, in der .NET Implementierung geht es.
Bei den meisten anderen (und auch bei der Vorauswahl) geht es aus besagtem Grund nicht.
Gerade auch in meiner Anwendung getestet: Funktioniert dort natürlich auch.
Damit hätte ich mir den kompletten Thread hier sparen können, denn dieses Pattern mit Lookbehind war auch mein erster Versuch.
Jetzt überlege ich, ob ich die MaxMatches Eigenschaft wieder raus werfe und auf den ursprünglichen Ansatz zurück gehe.
Vermutlich mache ich das.