Regex - Suche nach Text innerhalb Start und Ende Tag

  • C#
  • .NET 7–8

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von mrMo.

    Regex - Suche nach Text innerhalb Start und Ende Tag

    Moin,

    ich verzweifle mal wieder an Regex.

    In einer Textdatei stehen mehrere Datensätze, die jeweils von einem Starttag (BEGIN) bis zu einem Endtag (END) gehen. Einzelne Datenfelder liegen jeweils in einer Zeile. Ich will jetzt mit Regex alles was zwischen Starttag und Endtag steht, herausfiltern.

    BEGIN
    NAME: PUMUCKL
    HAARFARBE: ORANGE
    END
    BEGIN
    NAME: EDER
    HAARFARBE: KEINE
    BESONDERHEIT: HALBGLATZE
    END



    Bisher sieht das so aus:

    C#-Quellcode

    1. var pattern = @"((?=BEGIN)(.)*(END))";
    2. var matches = Regex.Matches(_text!, pattern, RegexOptions.Singleline);
    3. var match = Regex.Match(_text!, pattern, RegexOptions.Singleline);


    Das Problem ist, dass Matches gar nix findet und Match alles.

    Genauer:
    Match findet alles vom ersten BEGIN bis zum letzten END und nicht, wie vielleicht gedacht, vom ersten BEGIN bis zum ersten END.

    Ich konsultiere normalerweise folgende Webseite: regexr.com/. Dort zeigt sich, dass der entscheidende Unterschied, was gefunden wird, im Global-Flag liegt. Mit dem Global-Flag sucht er nach mehreren Vorkommen des Suchstrings, ohne nur nach dem ersten.

    Dort eingebenes Pattern: /(ABC)(.)+(CBA)/g und folgender Text:

    123ABC321CBA098
    123ABC321CBA098

    Der Teil, der dem Pattern laut Webseite entspricht, habe ich hier fett hervorgehoben. Lasse ich das Global Flag (/g) weg , dann wir nur der erste Teil als Fund markiert.

    Ich finde in C# kein Pendant zu diesem Flag. Ich denke, das sollte Matches und Match sein. Aber irgendwie bringe ich das nicht zusammen.

    Und sowieso, warum findet Matches nix?

    Ich weiß, dass es mehrere Dialekte für reguläre Ausdrücke gibt. Ich finde aber keine Hinweise auf regex.com und in der Microsoft Dokumentation learn.microsoft.com/en-us/dotn…-language-quick-reference die mir da weiterhelfen.

    C# verhält sich nicht so, wie ich es aus der Dokumentation herauslese, bzw. verstehe.

    Wo liegt der Fehler?

    Gruß

    Joachim

    ___
    EDIT:

    Oh mann, mit dem Pattern

    (BEGIN:VCARD).*?(END:VCARD) funktionierts. Was so ein "?" alles ausmacht!



    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „MasterQ“ ()

    Ein Punkt . findet keine Zeilenenden, muss extra mit \n
    BEGIN\n(?:.*\n)*?END\n?
    Captured dir schonmal jedes BEGIN END Paket.
    BEGIN und END selbst kannst du rausnehmen in dem du noch eine Capturing Group einbaust oder mit Lookahead, aber ich würds lieber drin lassen und im Result kannst es ja genauso gut ersetzen. Es ist ja immer die gleiche Zeichenfolge.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    @Haudruferzappeltnoch, @MasterQ

    Ich würde an der Stelle kein ​. und auch kein ​.? verwenden, sondern die Character-Klassen ​\s\S verwenden. Die suchen nach allen Whitespace und non-Whitespace Chars.
    Damit hättest du eigentlich genau das, was du brauchst.

    Andererseits, würde ich persönlich hier nicht mit regulären Ausdrücken vorgehen, sondern den Output Zeile für Zeile parsen.
    Du kannst den String super als Tokens aufbereiten und dann entsprechend in Sektionen aufteilen.
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.
    Ganz grob zusammengefasst:
    (
    Quelle hier: docs.oracle.com/javase/7/docs/…regex/Pattern.html#predef
    Verhält sich bei Regex aber immer gleich :)
    )

    . => Alle zeichen (garantiert aber nicht, dass Zeilenendungen mitgematcht werden)
    \s => Alle Weißzeichen, inkl CR (carriage return => \r), LF (line feed => \n), NL => (next line => fileformat.info/info/unicode/char/0085/index.htm), LS (line separator => fileformat.info/info/unicode/char/2028/index.htm), und PS (paragraph separator => fileformat.info/info/unicode/char/2029/index.htm).

    EDIT:
    Fipptehler behoben Dank Post #6
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „siycah“ ()

    Huch, haste Recht. Da ist mir die Shift-Taste wohl reingeruscht. Mein Fehler.

    Natürlich meine ich ​\s in dem Fall.

    Warum man die Character-Klasse bevorzugen sollte, ist Plattformkompatibilität.
    Wie oben schon geschrieben kann ​. auch andere Zeichen matchen, aber es liegt an der Implementierung, was für den ​. ein Zeilenende ist.
    ​\s\S ist dagegen plattformübergreifend vom Verhalten gleich.
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.
    Du simulierst da leider nicht, dass ein anderes Zeilenende genommen wird.
    Ich schaue mal, dass ich die Tage ein vollständiges Beispiel baue.

    Meine Erfahrungen im Embedded Bereich (auch Windows) haben gezeigt, dass ​. nicht zuverlässig (genug) läuft.
    V.a. wenn man andere Programmiersprachen als die auf der .net-Plattformen verwendet.
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.
    Korrekt. \n ist nur das. Es ist nur \n. Es matcht nicht mit \r, nicht mit den anderen Zeichen, die ich aufgelistet habe.

    Es gibt auch noch andere Betriebssysteme, außer Windows. Auch welche, die weder \r, noch \n als Zeilenende verwenden.
    Selbst in der Linux-Welt ist es nicht zwingend gegeben, dass alles darauf endet. Und genau da schlägt dein Regex fehl.

    Mag sein, dass das (.\n) für die allermeisten Zwecke ausreichend ist. Zweifel ich nicht an.
    Allerdings ist das kein Alleskönner wie du hier gerade meinst.
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.
    Die Datenstruktur sieht ja recht klar aus. Daher würde ich es Zeilenweise (hat Kollege @siycah auch schon vorgeschlagen) verarbeiten und die „Datenzeilen“ beim Doppelpunkt splitten.
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen