web-dev-qa-db-de.com

std :: regex, um Anfang und Ende der Zeichenfolge zu finden

In JS regulären Ausdrücken symbolisieren ^ und $ designate Anfang und Ende der Zeichenfolge . Und nur mit dem /m-Modifizierer (Multiline-Modus) stimmen sie mit Anfang und Ende der Zeile - Position vor und nach CR/LF überein.

In std :: regex / ECMAscript - Moduszeichen ^ und $ stimmen jedoch mit Anfang und Ende der Zeile immer überein.

Gibt es in std :: regex eine Möglichkeit, Anfang und Ende der Zeichenfolge Übereinstimmungspunkte zu definieren? Mit anderen Worten: Unterstützung des JavaScript Multiline-Modus ...

11
c-smile

Standardmäßig behandelt der ECMAscript-Modus ^ bereits als Anfang der Eingabe und Anfang der Zeile und $ als beide Ende der Eingabe und Ende der Zeile. Es gibt keine Möglichkeit, sie an nur Anfang oder Ende der Eingabe anzupassen, aber es ist möglich, dass sie Nur Anfang oder Zeilenende übereinstimmen:

Beim Aufruf von std::regex_match , std::regex_search oder std::regex_replace gibt es ein Argument vom Typ std::regex_constants::match_flag_type , das standardmäßig std::regex_constants::match_default verwendet.

  • Um anzugeben, dass ^ nur mit dem Zeilenanfang übereinstimmt, geben Sie std::regex_constants::match_not_bol an.
  • Um anzugeben, dass $ nur mit dem Zeilenende übereinstimmt, geben Sie std::regex_constants::match_not_eol an.
  • Da diese Werte Bitflags sind, können Sie beide einfach bitweise oder zusammen angeben (std::regex_constants::match_not_bol | std::regex_constants::match_not_eol).
  • Beachten Sie, dass der Anfang der Eingabe ohne Verwendung von ^ und unabhängig von der Anwesenheit von std::regex_constants::match_not_bol durch Angabe von std::regex_constants::match_continuous impliziert werden kann.

Dies wird gut in der ECMAScript-Grammatikdokumentation on cppreference.com erklärt, die ich generell über cplusplus.com wärmstens empfehlen kann.

Vorbehalt: Ich habe mit MSVC, Clang + libc ++ und Clang + libstdc ++ getestet, und nur MSVC hat derzeit das richtige Verhalten.

6
ildjarn

^ und $ stimmen mit Beginn und Ende von string überein, nicht mit einer Zeile. Siehe diese Demo die in "1\n2\n3" keine Übereinstimmung mit ^\d+$ regex findet. Wenn Sie Alternativen hinzufügen (siehe unten), gibt es 3 Übereinstimmungen .

Es gibt keine Option in std::regex, damit die Anker mit dem Anfang und dem Ende der Linie übereinstimmen. Sie müssen es mit Änderungen simulieren:

^ -> (^|\n)
$ -> (?=\n|$)

Beachten Sie, dass $ vollständig mit (?=\n|$) "emuliert" werden kann (wobei Sie möglicherweise weitere Zeilenabschlusszeichen oder Symbolsequenzen wie (?=\r?\n|\r|$) hinzufügen). Mit ^ können Sie jedoch keine 100% ige Problemumgehung finden.

Da es keine Unterstützung für Lookbehind gibt, müssen Sie möglicherweise andere Teile Ihres Regex-Musters anpassen, da (^|\n) Capture-Gruppen häufiger verwendet als bei einer Lookbehind-Unterstützung.

4

Sie können Perl/Python/PCRE \A Emulieren, das am Anfang der Zeichenfolge, jedoch nicht nach einem Zeilenumbruch, mit der JavaScript-Regex ^(?<!(.|\n)]) übereinstimmt Zeile ohne vorangestelltes Zeichen ".

Sie können Perl/Python/PCRE \z Emulieren, das nur am Ende der Zeichenfolge mit (?!(.|\n))$ Übereinstimmt. Um den Effekt von \Z Zu erhalten, der nur am Ende der Zeichenfolge übereinstimmt, aber eine einzelne neue Zeile direkt vor diesem Ende der Zeichenfolge zulässt, fügen Sie einfach eine optionale neue Zeile hinzu: \n?(?!(.|\n))$.

0
Thom Boyer

Das folgende Code-Snippet vergleicht E-Mail-Adressen, die mit [a-z] beginnen, gefolgt von 0 oder 1 Punkt, dann mit 0 oder mehr a-z-Buchstaben und anschließend mit "@ gmail.com". Ich habe es getestet.

string reg = "^[a-z]+\\.*[a-z]*@gmail\\.com$";

regex reg1(reg, regex_constants::icase);
reg1(regex_str, regex_constants::icase);
string email;
cin>>email;
if (regex_search(email, reg1))
0
Charlie