Suche regulären ausdruck für Id Liste



  • Hallo zusammen,

    die Frage ist wahrscheinlich trivial, aber ich kenne mich leider schlecht mit regulären Ausdrücken aus und stehe da total auf dem Schlauch und bitte daher um Nachsicht.

    Ich habe eine Textzeile die wie folgt aussieht:
    (0x0020011c,IDs:2,3,4,8,15,2a;0x00000003)
    Die drei Teile nenne ich nachfolgend IDhex1, ID-List, IDhex2.

    IDhex1 und IDhex2 sind Hexadezimalwerte fester länge. ID-List ist eine liste von Hexadezimalwerten mit praktisch beliebiger Länge.

    Der Teil ID-List ist optional, daher kann das auch folgendermaßen aussehen:
    (0x0020011c;0x00000003)

    Ich interessieren mich für die Teile IDhex1 und ID-List, wobei bei ID-List nur die Liste, also der teil nach dem "IDs:" interessant ist. Wie sähe ein std::regex aus, mit dem ich beides extrahieren kann?



  • Hausaufgaben? Was zahlst du?



  • oenone schrieb:

    Hausaufgaben? Was zahlst du?

    Ich gehe lange nicht mehr zur Schule und als "Gegenleistung" kann ich leider nur anbieten, hier weiterhin die ein oder andere Frage zu beantworten (Was ich ohnehin machen werde, egal ob ich eine Antwort bekomme oder nicht). Wenn das nicht reicht ist das halt so.


  • Mod

    Was zahlst du?

    Wenn du nicht die Motivation hast es ohne Gegenleistung zu tun, hast du in diesem Forum eine merkwürdige Doppelmoral. Die Frage hat m.E.n. mehr als genug Eigeninitiative.

    Ich schlage mal

    #include <regex>
    #include <iostream>
    
    int main()
    {
    	std::regex reg( R"(\((0[xX][0-9a-fA-F]+)(,IDs:([0-9a-f]+(,[0-9a-f]+)*))?;.+\))" );
    
    	std::string str = "(0x0020011c,IDs:2,3,4,8,15,2a;0x00000003)";
    
    	std::smatch match;
    	if (std::regex_match(str, match, reg))
    		std::cout << match[1] << ' ' << match[3];
    }
    

    vor, aber wie bereits anderswo erwähnt bin ich kein Regex-Experte; warte also lieber noch auf eine saubere Lösung.

    Edit: Hier noch mal der Stacked-Crooked Link.



  • Wie sieht es mit Leerzeichen aus? Nach Vorlage hätte ich es so interpretiert:

    "\\(0[xX][0-9a-fA-F]{8}(,IDs:[0-9a-fA-F]+(,[0-9a-fA-F]+)*)?;0[xX][0-9a-fA-F]{8}\\)"
    


  • Ich denke das sieht schon nicht so schlecht aus soweit ich das nachvollziehen kann, aber zu den IDs: Ich denke die ID liste könnte theoretisch auch leer sein, also etwa (0x0020011c,IDs:;0x00000003) auch interesiert mich nur die Liste ansich, also bei IDs:2,3,4,8,15,2a nur 2,3,4,8,15,2a.



  • Mein Ansatz basierend auf Arcoths Vorarbeit:

    #include <regex>
    #include <iostream>
    
    int main() {
      std::regex reg(
          R"(\((0x[\da-f]+)(?:,IDs:([\da-f]+(?:,[\da-f]+)*)?)?;(0x[\da-f]+)\))",
          std::regex_constants::icase);
    
      std::smatch match;
      for (auto str : { "(0x0020011c,IDs:2,3,4,8,15,2a;0x00000003)",
                        "(0x0020011c,IDs:;0x00000003)",
                        "(0x0020011c;0x00000003)", })
        if (std::regex_match(std::string(str), match, reg)) {
          std::cout << "IDHex1: " << match[1];
          if (match[2] != "") std::cout << ", ID-List: " << match[2];
          std::cout << ", IDHex2: " << match[3] << '\n';
        }
    }
    

    Ausgabe:

    IDHex1: 0x0020011c, ID-List: 2,3,4,8,15,2a, IDHex2: 0x00000003
    IDHex1: 0x0020011c, IDHex2: 0x00000003
    IDHex1: 0x0020011c, IDHex2: 0x00000003
    

    Habe den Regex mal Case insensitive gemacht, damit ich weniger schreiben muss und er etwas performanter ist. (Er matcht dann auch ids statt IDs.)

    Mit ?: kann man unbenannte Gruppen machen, dann reduziert den Overhead wieder etwas und match ist schön aufgeräumt. Dann noch \d statt 0-9 weil das ein Zeiche einspart.



  • Wenn du den Regex nur benutzen willst um den String zu splitten (und ihn dann nachträglich selber validierst) kannst du auch

    R"(\((\w+)(?:,IDs:([\w,]*));(\w+)\))"
    

    verwenden.

    Mit Leerzeichen kommt der auch nicht zurecht.



  • Die Antworten sind schon sehr hilfreich. Vielen Dank euch allen.


Anmelden zum Antworten