String aus Regex generieren mittels Group-Zuordnung?

  • VB.NET

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von Elodin.

    String aus Regex generieren mittels Group-Zuordnung?

    Liebes Forum,

    bislang war ich stiller Mitleser und konnte nach meinem Umstieg auf vb.NET schon viel von euch mitnehmen, besten Dank dafür! Jetzt habe ich allerdings ein Problem, zu dem ich weder hier noch auf anderen Seiten eine Lösung finde (sofern es überhaupt eine gibt ...). Vielleicht bin ich gänzlich auf dem Holzweg.

    Ziel: Funktion, die als Parameter eine Steuernummer im alten Format als String erhält und ins neue Bundesschema umwandelt.
    Herausforderung: Altes wie neues Schema sind von Bundesland zu Bundesland verschieden. Es ist nicht bekannt, aus welchem Bundesland die Steuernummer stammt.
    Aktueller Ansatz: Die Patterns der Steuernummern als Regular Expressions in zwei Arrays speichern, eines für das alte Schema, eines für das neue. Die (bereits validierte) Steuernummer wird in einer For-Schleife mit den alten Patterns verglichen. Bei einem Match soll sie mittels des neuen Patterns ins neue Schema umgewandelt werden.

    VB.NET-Quellcode

    1. For i As Integer = 0 To patternStNrAlt.Length - 1 ' Array mit Regex-Patterns als Strings, eines pro Bundesland
    2. If Regex.Match(strSteuernummer, patternStNrAlt(i)).Success Then ' vergleicht den String mit den Patterns
    3. strSteuernummerNeu = 'hier soll die neue Steuernummer zusammengebaut werden
    4. Return strSteuernummerNeu
    5. End If
    6. Next


    Beispiel:
    - strSteuernummer = "93815/08152"
    - Matcht bei i = 0 mit "^(?<ff>\d{2})(?<bbb>\d{3})[/](?<uuuu>\d{4})(?<p>\d{1})$"
    - patternStNrNeu(0) = "^28(?<ff>\d{2})0(?<bbb>\d{3})(?<uuuu>\d{4})(?<p>\d{1})$"
    - Nun müssen alle Ziffern der jeweiligen Gruppen korrekt angeordnet als neuer String "zusammengebastelt" werden. Sprich: Die Ziffern, die vorher in der Gruppe <ff> waren, sollen auch beim neuen Pattern an der Stelle <ff> stehen.
    - Rückgabewert: strSteuernummerNeu = "2893081508152"

    Meine Frage: Gibt es einen einfachen, geschickten Weg Zeile 3 des obigen Codes umzusetzen?

    Meine beste Idee wäre, die Gruppennamen und -werte in ein Dictionary zu speichern und dann mit einem Select Case für jedes einzelne Bundesland den neuen String händisch wieder zusammenzusetzen ... Aber das muss doch auch geschickter gehen?


    VB.NET-Quellcode

    1. Dim rgx As New Regex(patternStNrAlt(i))
    2. Dim match As Match = rgx.Match(strSteuernummer)
    3. Dim strGroupNames() As String = rgx.GetGroupNames()
    4. Dim dictGroupZiffern As New Dictionary(Of String, String)
    5. For j As Integer = 0 To strGroupNames.Length - 1
    6. Dim grp As Group = match.Groups.Item(strGroupNames(j))
    7. dictGroupZiffern.Add(strGroupNames(j), grp.Value)
    8. Next
    9. 'Select Cases auf i und je nach Fall/Bundesland neuen String händisch mittels Dictionary zusammenbauen
    Bau dir eine Klasse "SteuernummerMapping", die den Regex der alten und einen FormatString der neuen Steuernummer in einem Objekt zusammenfasst. Meinetwegen zusammen mit dem Bundesland, für das das gilt.
    Tu davon Instanzen für alle Bundesländer in eine Liste - kein Dictionary.
    Kommt eine Steuernummer, probierst du alle mappings aus, und wo der Regex matcht, da wendest du dann den FormatString an, um die neue Steuernummer zu bilden.
    Bindeglied zw. alt und neu müssen tatsächlich die Gruppen-Namen der Regexe sein, damit der Wert der Gruppe <ff> dann an der richtigen Stelle im format-String eingebettet ist.

    Kann auch sein, dass das garnet geht, also dass man nicht einfach die Gruppen-Values der Regexe zur neuen Steuernummer zusammensetzen kann - weiss ich ja nicht, du hast ja bislang keine Beispiele gegeben.
    Oder die Mappings sind nicht eindeutig, sodass evtl. Mappings verschiedener BuLas auf dieselbe Steuernummer matchen.
    Ein Consolen Testprogramm für BW und NRW:

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. Module Module1
    4. Sub Main()
    5. Dim StNrNeu As String = ""
    6. Dim StNrAlt As String = ""
    7. Dim Land As String
    8. StNrAlt = "93815/08152"
    9. Land = "BW"
    10. StNrNeu = NeueNr(StNrAlt, Land)
    11. Debug.Print(Land & " - Alt: " & StNrAlt & " - Neu: " & StNrNeu)
    12. StNrAlt = "133/8150/8159"
    13. Land = "NRW"
    14. StNrNeu = NeueNr(StNrAlt, Land)
    15. Debug.Print(Land & " - Alt: " & StNrAlt & " - Neu: " & StNrNeu)
    16. End Sub
    17. Function NeueNr(AlteNr As String, BLand As String) As String
    18. Dim FF, BB, UU, P As String
    19. AlteNr = AlteNr.Trim
    20. BLand = BLand.ToUpper.Trim
    21. Select Case BLand
    22. Case "BW"
    23. FF = AlteNr.Substring(0, 2)
    24. BB = AlteNr.Substring(2, 3)
    25. UU = AlteNr.Substring(6, 4)
    26. P = AlteNr.Substring(10, 1)
    27. NeueNr = String.Concat("28", FF, "0", BB, UU, P)
    28. Case "NRW"
    29. FF = AlteNr.Substring(0, 3)
    30. BB = AlteNr.Substring(4, 4)
    31. UU = AlteNr.Substring(9, 3)
    32. P = AlteNr.Substring(12, 1)
    33. NeueNr = String.Concat("5", FF, "0", BB, UU, P)
    34. Case Else
    35. NeueNr = "Land ist falsch"
    36. End Select
    37. End Function
    38. End Module

    Quellcode

    1. ______ __
    2. / ____/ (_) ___ _____ / / ___ (_) ____
    3. / __/ / / / _ \ / ___/ / / / _ \ / / / __ \
    4. / /___ / / / __/ / / / / / __/ / / / / / /
    5. /_____/ /_/ \___/ /_/ /_/ \___/ /_/ /_/ /_/
    Ich glaube, du meintest sowas:

    VB.NET-Quellcode

    1. Imports System.Text.RegularExpressions
    2. Module Module1
    3. Sub Main()
    4. Dim arr(2) As String
    5. arr(0) = "(\d{3})/(\d{3})/(\d{5})" 'Bayern
    6. arr(1) = "(\d{5})/(\d{5})" 'BW
    7. arr(2) = "(\d{3})/(\d{4})/(\d{4})" 'NRW
    8. Dim ReplArr(2) As String
    9. replArr(0) = "9$1'0$2$3" 'Bayern
    10. ReplArr(1) = "28S1'0$2$3" 'BW
    11. ReplArr(2) = "5$10$2$3" 'NRW
    12. Dim tmp As String = ""
    13. Dim t$ = ""
    14. 't = "z. B. 181/815/08155 " 'Bayern
    15. t = "133/8150/8159" 'NRW
    16. 't = "93815/08152" 'BW
    17. For i As Integer = 0 To 2
    18. If Regex.IsMatch(t, arr(i)) Then
    19. tmp = Regex.Replace(t, arr(i), ReplArr(i))
    20. tmp = tmp.Replace("'", "")
    21. Exit For
    22. End If
    23. Next
    24. Debug.Print(tmp)
    25. End Sub
    26. End Module
    Vielen Dank für eure Antworten!

    ErfinderDesRades schrieb:

    Bau dir eine Klasse "SteuernummerMapping", die den Regex der alten und einen FormatString der neuen Steuernummer in einem Objekt zusammenfasst. Meinetwegen zusammen mit dem Bundesland, für das das gilt.
    Tu davon Instanzen für alle Bundesländer in eine Liste - kein Dictionary.
    Kommt eine Steuernummer, probierst du alle mappings aus, und wo der Regex matcht, da wendest du dann den FormatString an, um die neue Steuernummer zu bilden.
    Bindeglied zw. alt und neu müssen tatsächlich die Gruppen-Namen der Regexe sein, damit der Wert der Gruppe <ff> dann an der richtigen Stelle im format-String eingebettet ist.

    Du hast recht, eine Liste wäre deutlich sinnvoller als ein Dictionary. Mein erster Ansatz war tatsächlich eine Klasse, aber ich hätte es gerne "simpler" gelöst - vermutlich ist das Problem zu umfangreich für eine "einfache" Funktion. Ich versuche es nochmal als Klasse, ich bin ja noch am Lernen.

    ErfinderDesRades schrieb:

    Kann auch sein, dass das garnet geht, also dass man nicht einfach die Gruppen-Values der Regexe zur neuen Steuernummer zusammensetzen kann - weiss ich ja nicht, du hast ja bislang keine Beispiele gegeben.
    Oder die Mappings sind nicht eindeutig, sodass evtl. Mappings verschiedener BuLas auf dieselbe Steuernummer matchen.

    Ich weiß nicht, ob es "einfach" geht. Händisch auf jeden Fall. Ich hatte gehofft, dass es eine Regex-Methode gibt, die ich bei meiner Recherche nicht gefunden oder falsch verstanden habe. Die Regex.Replace-Methode sah auf den ersten Blick vielversprechend aus, aber sie bekommt das mit den Gruppen nicht gebacken (zumindest bekomme ich es nicht mit ihr gebacken :D).
    Das Mapping wird nicht eindeutig sein, aber dafür habe ich schon eine Lösungsidee, die ich noch ausprobieren werde.

    Vielen Dank für deine Code-Beispiele, Eierlein! Vom Grundprinzip her ging meine Lösungsidee in die Richtung deines ersten Testprogramms, nur dass ich die Werte aus der alten Steuernummer mittels der Gruppenzuordnung herausgeschnitten habe und dann im nächsten Schritt für jedes Bundesland manuell zusammengesetzt hätte.
    Dein zweites Beispiel werde ich gleich in Ruhe nachvollziehen. Auf jeden Fall hast du mich auf eine Idee gebracht, wie ich Regex.Replace vielleicht doch sinnvoll nutzen kann.