2016-04-11 7 views
1

Ich möchte wissen, wie ich den Namen von Capture-Gruppe (n) in einem regulären Ausdruck in Boost bekommen kann.Liste der benannten Captures/Gruppen in Boost Regex

Zum Beispiel, wenn ein Benutzer eine Zeichenfolge eingibt, von der erwartet wird, dass sie eine gültige Regex mit benannten Erfassungsgruppen ist, wie kann man durch die Liste definierter Gruppen in der Regex iterieren und die Namen dieser Gruppen erhalten. Bietet Boost die Möglichkeit, dies zu tun, oder wird von mir erwartet, dass ich meinen eigenen Parser schreibe, um diese Namen zu extrahieren?

Als Beispiel, wenn die Eingabezeichenfolge ist:

(?<year>[0-9]{4}).*(?<month>[0-9]{2}).*(?<day>[0-9]{2}) 

ich will „Jahr“ in der Lage sein zu extrahieren, „Monat“ und „Tag“ aus dem regulären Ausdruck.

+0

Möglicherweise könnten Sie die Regex in einen Boost-Regex kompilieren und dann die Capture-Namen daraus abrufen. Sie könnten dies tun, aber es gibt ein Problem mit benannten Unterausdrücken. Wenn die Regex analysiert wird, wird jeder Name technisch in einen Hash umgewandelt und in einen Vektor eingefügt, wobei die weitere Referenz über eine ID erfolgt. Sehen Sie sich 'class named_subeexpressions' in boost_regex.hpp an. Es kann geändert werden, um eine Zuordnung der tatsächlichen String-Namen zu erstellen. Hier können Sie einen Anruf hinzufügen, um den indexierten Gruppennamen zurückzubekommen. – sln

+0

(Entschuldigung, die Quelle sollte basic_regex.hpp sein) Ich kann die paar Zeilen posten, die das tun, aber Sie müssten die Engine neu kompilieren. Und ich bin mir nicht sicher, ob das legal ist. – sln

+0

Es wäre so etwas wie 'classnamed_subexpressions {public: ... voidset_name (constcharT * i, constcharT * j, intindex) {... std :: stringstmp (i, j); intalen = (int) stmp.length (); if (alen> 0) {längste_name = alen> längste_name? alen: längste_name; m_sub_sNamen [index] = stmp;}} std :: zeichenkette_name (intndx) const {if (längste_name> 0) {autogroupName = m_sub_sNames.find (ndx); if (groupName! = m_sub_sNames.end()) returngroupName-> Sekunde;} return "";} intget_longest_namelen() {returnlongest_name;} privat: inlongest_name; std :: map m_sub_sNames; ...}; ' – sln

Antwort

0

können Sie folgende regex verwenden:

"\?<([^<>]+)>" 

Ich glaube nicht, dass regex Motoren solche Möglichkeit bieten, die Namen der erfassten Gruppen zu geben, bevor die Regex kompilieren, weil sie die Eingabe regex zu durchlaufen muss einmal vor dem Parsen (und Kompilieren) der Regex, was keine optimale Methode ist, es sei denn, es kompiliert die Regex einmal und führt alle Jobs zusammen aus.

Also, in Bezug auf Ihren Kommentar, wenn es möglich ist, dass Sie eine unbenannte Gruppe haben, besser Sie Schleife über Ihre erfassten Gruppen und sehen, ob es Namen hat oder nicht.

Beachten Sie, dass Sie vielleicht die Fälle, die unbenannte Gruppen mit Regex haben, analysieren könnten, aber ich denke nicht, dass es ein allgemeiner Weg ist.

Zum Beispiel können Sie die oben genannten regex in Klammern verwenden, um alle Gruppen zu erfassen, die nicht eine andere Capture-Gruppe in ihnen tun ([^()]* wird sichergestellt, dass):

`\((\?<([^<>]+)>)[^()]*\)` 

und zum anderen Fällen müssen Sie schreibe einen anderen.

+0

Danke für deine Antwort. Ich war neugieriger zu wissen, ob dies von Regex-Engines zur Verfügung gestellt wird oder nicht. Ich habe versucht, eine solche Einrichtung zu finden, aber vergebens. Haben Sie eine Idee, wie Sie zu welcher Capture-Gruppe der extrahierte Name gehört? Angenommen, die zweite Erfassungsgruppe wird nicht im Eingangsregex benannt ... '(? [0-9] {4}). * ([0-9] {2}). * (? [0-9] {2}) 'können wir herausfinden, dass sich dieser Tag tatsächlich auf die dritte Fanggruppe bezieht? – Arash

+0

@Arash Willkommen, bitte überprüfen Sie die Bearbeitung. – Kasramvd