Namespaces
Variants

Modified ECMAScript regular expression grammar

From cppreference.net

Diese Seite beschreibt die Grammatik regulärer Ausdrücke, die verwendet wird, wenn std::basic_regex mit syntax_option_type auf ECMAScript gesetzt erstellt wird (der Standardwert). Siehe syntax_option_type für die anderen unterstützten Grammatiken regulärer Ausdrücke.

Die ECMAScript 3 reguläre Ausdrucksgrammatik in C++ ist die ECMA-262 Grammatik mit unten markierten Modifikationen (nur C++) .

Inhaltsverzeichnis

Übersicht

Die modifizierte reguläre Ausdrucksgrammatik ist größtenteils ECMAScript RegExp-Grammatik mit einer POSIX-artigen Erweiterung für Locales unter ClassAtom . Einige Klarstellungen zu Gleichheitsüberprüfungen und Zahlenparsing wurden vorgenommen. Für viele der Beispiele hier können Sie dieses Äquivalent in Ihrer Browser-Konsole ausprobieren:

function match(s, re) { return s.match(new RegExp(re)); }

Die "normativen Referenzen" im Standard spezifizieren ECMAScript 3. Wir verlinken hier auf die ECMAScript 5.1-Spezifikation, da es sich um eine Version mit nur geringfügigen Änderungen gegenüber ECMAScript 3 handelt und sie auch eine HTML-Version verfügbar hat. Siehe den MDN-Leitfaden zu JavaScript RegExp für einen Überblick über die Dialektfunktionen.

Alternativen

Ein regulärer Ausdrucksmuster ist eine Sequenz von einem oder mehreren Alternative n, getrennt durch den Disjunktionsoperator | (mit anderen Worten, der Disjunktionsoperator hat die niedrigste Priorität).

Pattern ::

Disjunktion

Disjunktion ::

Alternative
Alternative | Disjunktion

Das Muster versucht zunächst, die Disjunction zu überspringen und die linke Alternative gefolgt vom Rest des regulären Ausdrucks (nach der Disjunction) zu matchen.

Wenn es fehlschlägt, versucht es, die linke Alternative zu überspringen und die rechte Disjunktion abzugleichen (gefolgt vom Rest des regulären Ausdrucks).

Wenn die linke Alternative , die rechte Disjunktion und der Rest des regulären Ausdrucks alle Wahlpunkte haben, werden alle Optionen im Rest des Ausdrucks ausprobiert, bevor zur nächsten Option in der linken Alternative übergegangen wird. Wenn die Optionen in der linken Alternative erschöpft sind, wird stattdessen die rechte Disjunktion anstelle der linken Alternative versucht.

Jede erfassende Klammer innerhalb eines übersprungenen Alternative erzeugt leere Teilübereinstimmungen.

#include <cstddef>
#include <iostream>
#include <regex>
#include <string>
void show_matches(const std::string& in, const std::string& re)
{
    std::smatch m;
    std::regex_search(in, m, std::regex(re));
    if (!m.empty())
    {
        std::cout << "input=[" << in << "], regex=[" << re << "]\n  "
                     "prefix=[" << m.prefix() << "]\n  smatch: ";
        for (std::size_t n = 0; n < m.size(); ++n)
            std::cout << "m[" << n << "]=[" << m[n] << "] ";
        std::cout << "\n  suffix=[" << m.suffix() << "]\n";
    }
    else
        std::cout << "input=[" << in << "], regex=[" << re << "]: NO MATCH\n";
}
int main()
{
    show_matches("abcdef", "abc|def");
    show_matches("abc", "ab|abc"); // left Alternative matched first
    // Match of the input against the left Alternative (a) followed
    // by the remained of the regex (c|bc) succeeds, which results
    // in m[1]="a" and m[4]="bc".
    // The skipped Alternatives (ab) and (c) leave their submatches
    // m[3] and m[5] empty.
    show_matches("abc", "((a)|(ab))((c)|(bc))");
}

Ausgabe:

input=[abcdef], regex=[abc|def]
  prefix=[]
  smatch: m[0]=[abc]
  suffix=[def]
input=[abc], regex=[ab|abc]
  prefix=[]
  smatch: m[0]=[ab]
  suffix=[c]
input=[abc], regex=[((a)|(ab))((c)|(bc))]
  prefix=[]
  smatch: m[0]=[abc] m[1]=[a] m[2]=[a] m[3]=[] m[4]=[bc] m[5]=[] m[6]=[bc]
  suffix=[]

Begriffe

Jede Alternative ist entweder leer oder eine Sequenz von Term s (ohne Trennzeichen zwischen den Term s)

Alternative ::

[leer]
Alternative Bezeichnung

Leere Alternative stimmt immer überein und verbraucht keine Eingabe.

Aufeinanderfolgende Term e versuchen gleichzeitig aufeinanderfolgende Abschnitte der Eingabe abzugleichen.

Wenn die linke Alternative , der rechte Term und der Rest des regulären Ausdrucks alle Wahlpunkte haben, werden alle Möglichkeiten im Rest des Ausdrucks ausprobiert, bevor zur nächsten Option im rechten Term übergegangen wird, und alle Möglichkeiten im rechten Term werden ausprobiert, bevor zur nächsten Option in der linken Alternative übergegangen wird.

#include <cstddef>
#include <iostream>
#include <regex>
#include <string>
void show_matches(const std::string& in, const std::string& re)
{
    std::smatch m;
    std::regex_search(in, m, std::regex(re));
    if (!m.empty())
    {
        std::cout << "input=[" << in << "], regex=[" << re << "]\n  "
                     "prefix=[" << m.prefix() << "]\n  smatch: ";
        for (std::size_t n = 0; n < m.size(); ++n)
            std::cout << "m[" << n << "]=[" << m[n] << "] ";
        std::cout << "\n  suffix=[" << m.suffix() << "]\n";
    }
    else
        std::cout << "input=[" << in << "], regex=[" << re << "]: NO MATCH\n";
}
int main()
{
    show_matches("abcdef", ""); // leere Regex ist eine einzelne leere Alternative
    show_matches("abc", "abc|"); // linke Alternative wird zuerst gematcht
    show_matches("abc", "|abc"); // linke Alternative wird zuerst gematcht, lässt abc ungematcht
}

Ausgabe:

input=[abcdef], regex=[]
  prefix=[]
  smatch: m[0]=[]
  suffix=[abcdef]
input=[abc], regex=[abc|]
  prefix=[]
  smatch: m[0]=[abc]
  suffix=[]
input=[abc], regex=[|abc]
  prefix=[]
  smatch: m[0]=[]
  suffix=[abc]

Quantifizierer

  • Jeder Term ist entweder eine Assertion (siehe unten), oder ein Atom (siehe unten), oder ein Atom unmittelbar gefolgt von einem Quantifier

Term ::

Assertion
Atom
Atom Quantifier

Jeder Quantifier ist entweder ein greedy Quantifier (der nur aus einem einzigen QuantifierPrefix besteht) oder ein non-greedy Quantifier (der aus einem QuantifierPrefix gefolgt vom Fragezeichen ? besteht).

Quantifier ::

QuantifierPrefix
QuantifierPrefix ?

Jedes QuantifierPrefix bestimmt zwei Zahlen: die minimale Anzahl der Wiederholungen und die maximale Anzahl der Wiederholungen, wie folgt:

QuantifierPrefix Minimum Maximum
* null unendlich
+ eins unendlich
? null eins
{ DecimalDigits } Wert von DecimalDigits Wert von DecimalDigits
{ DecimalDigits , } Wert von DecimalDigits unendlich
{ DecimalDigits , DecimalDigits } Wert von DecimalDigits vor dem Komma Wert von DecimalDigits nach dem Komma

Die Werte der einzelnen DecimalDigits werden durch Aufruf von std::regex_traits::value (Nur C++) für jede der Ziffern erhalten.

Ein Atom gefolgt von einem Quantifier wird so oft wiederholt, wie durch den Quantifier angegeben. Ein Quantifier kann non-greedy sein, wobei das Atom -Muster so wenige Male wie möglich wiederholt wird, während der Rest des regulären Ausdrucks noch übereinstimmt, oder es kann greedy sein, wobei das Atom -Muster so oft wie möglich wiederholt wird, während der Rest des regulären Ausdrucks noch übereinstimmt.

Das Atom -Muster ist das, was wiederholt wird, nicht die Eingabe, die es abgleicht, sodass verschiedene Wiederholungen des Atom verschiedene Eingabe-Teilzeichenfolgen abgleichen können.

Wenn sowohl das Atom als auch der Rest des regulären Ausdrucks Wahlpunkte haben, wird das Atom zuerst so oft (oder so selten, wenn non-greedy ) wie möglich gematcht. Alle Wahlmöglichkeiten im Rest des regulären Ausdrucks werden ausprobiert, bevor zur nächsten Wahl in der letzten Wiederholung des Atom übergegangen wird. Alle Wahlmöglichkeiten in der letzten (n-ten) Wiederholung des Atom werden ausprobiert, bevor zur nächsten Wahl in der vorletzten (n-1)-ten Wiederholung des Atom übergegangen wird; zu diesem Zeitpunkt kann sich herausstellen, dass mehr oder weniger Wiederholungen des Atom jetzt möglich sind; diese werden ausgeschöpft (wiederum beginnend mit entweder so wenigen oder so vielen wie möglich), bevor zur nächsten Wahl in der (n-1)-ten Wiederholung des Atom übergegangen wird und so weiter.

Die Atom' s-Captures werden jedes Mal gelöscht, wenn es wiederholt wird (siehe das "(z)((a+)?(b+)?(c))*" Beispiel unten)

#include <cstddef>
#include <iostream>
#include <regex>
#include <string>
void show_matches(const std::string& in, const std::string& re)
{
    std::smatch m;
    std::regex_search(in, m, std::regex(re));
    if (!m.empty())
    {
        std::cout << "input=[" << in << "], regex=[" << re << "]\n  "
                     "prefix=[" << m.prefix() << "]\n  smatch: ";
        for (std::size_t n = 0; n < m.size(); ++n)
            std::cout << "m[" << n << "]=[" << m[n] << "] ";
        std::cout << "\n  suffix=[" << m.suffix() << "]\n";
    }
    else
        std::cout << "input=[" << in << "], regex=[" << re << "]: NO MATCH\n";
}
int main()
{
    // gierige Übereinstimmung, wiederholt [a-z] 4-mal
    show_matches("abcdefghi", "a[a-z]{2,4}");
    // nicht-gierige Übereinstimmung, wiederholt [a-z] 2-mal
    show_matches("abcdefghi", "a[a-z]{2,4}?");
    // Auswahlpunkt-Reihenfolge für Quantifizierer führt zu einer Übereinstimmung
    // mit zwei Wiederholungen, wobei die erste die Teilzeichenkette "aa" abgleicht,
    // die zweite die Teilzeichenkette "ba" abgleicht und "ac" nicht abgeglichen wird
    // ("ba" erscheint in der Erfassungsklausel m[1])
    show_matches("aabaac", "(aa|aabaac|ba|b|c)*");
    // Auswahlpunkt-Reihenfolge für Quantifizierer ermöglicht dieser Regex
    // den größten gemeinsamen Teiler zwischen 10 und 15 zu berechnen
    // (die Antwort ist 5, und sie füllt m[1] mit "aaaaa")
    show_matches("aaaaaaaaaa,aaaaaaaaaaaaaaa", "^(a+)\\1*,\\1+$");
    // die Teilzeichenkette "bbb" erscheint nicht in der Erfassungsklausel m[4]
    // weil sie gelöscht wird, wenn die zweite Wiederholung des Atoms
    // (a+)?(b+)?(c) die Teilzeichenkette "ac" abgleicht
    // HINWEIS: gcc macht hier einen Fehler - es löscht nicht korrekt die
    // Erfassungsgruppe matches[4] wie von ECMA-262 21.2.2.5.1 gefordert,
    // und erfasst daher fälschlicherweise "bbb" für diese Gruppe.
    show_matches("zaacbbbcac", "(z)((a+)?(b+)?(c))*");
}

Ausgabe:

input=[abcdefghi], regex=[a[a-z]{2,4}]
  prefix=[]
  smatch: m[0]=[abcde]
  suffix=[fghi]
input=[abcdefghi], regex=[a[a-z]{2,4}?]
  prefix=[]
  smatch: m[0]=[abc]
  suffix=[defghi]
input=[aabaac], regex=[(aa|aabaac|ba|b|c)*]
  prefix=[]
  smatch: m[0]=[aaba] m[1]=[ba]
  suffix=[ac]
input=[aaaaaaaaaa,aaaaaaaaaaaaaaa], regex=[^(a+)\1*,\1+$]
  prefix=[]
  smatch: m[0]=[aaaaaaaaaa,aaaaaaaaaaaaaaa] m[1]=[aaaaa]
  suffix=[]
input=[zaacbbbcac], regex=[(z)((a+)?(b+)?(c))*]
  prefix=[]
  smatch: m[0]=[zaacbbbcac] m[1]=[z] m[2]=[ac] m[3]=[a] m[4]=[] m[5]=[c] 
  suffix=[]

Assertions

Assertion s entsprechen Bedingungen, nicht Teilzeichenketten der Eingabezeichenkette. Sie verbrauchen niemals Zeichen aus der Eingabe. Jede Assertion ist eine der folgenden

Assertion ::

^
$
\ b
\ B
( ? = Disjunktion )
( ? ! Disjunktion )

Die Assertion ^ (Anfang der Zeile) stimmt überein

1) Die Position unmittelbar nach einem LineTerminator Zeichen (dies wird möglicherweise nicht unterstützt) (bis C++17) (dies ist nur garantiert, wenn std::regex_constants::multiline (nur C++) aktiviert ist) (seit C++17)
2) Der Beginn der Eingabe (sofern nicht std::regex_constants::match_not_bol (C++ only) aktiviert ist)

Die Assertion $ (Ende der Zeile) stimmt überein

1) Die Position eines LineTerminator -Zeichens (dies wird möglicherweise nicht unterstützt) (bis C++17) (dies ist nur garantiert, wenn std::regex_constants::multiline (nur C++) aktiviert ist) (seit C++17)
2) Das Ende der Eingabe (sofern nicht std::regex_constants::match_not_eol (C++ only) aktiviert ist)

In den beiden obigen Assertionen und im Atom . unten ist LineTerminator einer der folgenden vier Zeichen: U+000A ( \n oder Zeilenvorschub), U+000D ( \r oder Wagenrücklauf), U+2028 (Zeilentrenner) oder U+2029 (Absatztrenner)

Die Assertion \b (Wortgrenze) trifft zu

1) Der Anfang eines Wortes (aktuelles Zeichen ist ein Buchstabe, Ziffer oder Unterstrich, und das vorherige Zeichen ist keines davon)
2) Das Ende eines Wortes (das aktuelle Zeichen ist kein Buchstabe, Ziffer oder Unterstrich, und das vorherige Zeichen ist eines davon)
3) Der Beginn der Eingabe, wenn das erste Zeichen ein Buchstabe, eine Ziffer oder ein Unterstrich ist (sofern nicht std::regex_constants::match_not_bow (C++ only) aktiviert ist)
4) Das Ende der Eingabe, wenn das letzte Zeichen ein Buchstabe, eine Ziffer oder ein Unterstrich ist (sofern nicht std::regex_constants::match_not_eow (nur C++) aktiviert ist)

Die Assertion \B (negative Wortgrenze) matcht alles AUSSER dem Folgenden

1) Der Beginn eines Wortes (das aktuelle Zeichen ist ein Buchstabe, Ziffer oder Unterstrich, und das vorherige Zeichen ist keines dieser Zeichen oder existiert nicht)
2) Das Ende eines Wortes (das aktuelle Zeichen ist kein Buchstabe, Ziffer oder Unterstrich (oder der Matcher befindet sich am Ende der Eingabe), und das vorherige Zeichen ist eines davon)

Die Assertion ( ? = Disjunction ) (Null-Breiten-Positive-Lookahead) trifft zu, wenn Disjunction an der aktuellen Position auf die Eingabe passen würde

Die Assertion ( ? ! Disjunction ) (Zero-Width Negative Lookahead) trifft zu, wenn Disjunction NICHT an der aktuellen Position auf die Eingabe passen würde.

Für beide Lookahead-Assertions wird beim Abgleichen der Disjunction die Position nicht vorangetrieben, bevor der Rest des regulären Ausdrucks abgeglichen wird. Außerdem wird, wenn die Disjunction auf mehrere Arten an der aktuellen Position abgeglichen werden kann, nur die erste Möglichkeit versucht.

ECMAScript verbietet das Zurückverfolgen in Lookahead-Disjunktionen, was das Verhalten von Rückverweisen in einen positiven Lookahead vom Rest des regulären Ausdrucks beeinflusst (siehe Beispiel unten). Rückverweise in den negativen Lookahead vom Rest des regulären Ausdrucks sind immer undefiniert (da die Lookahead-Disjunktion fehlschlagen muss, um fortzufahren).

Hinweis: Lookahead-Assertions können verwendet werden, um ein logisches UND zwischen mehreren regulären Ausdrücken zu erstellen (siehe Beispiel unten).

#include <cstddef>
#include <iostream>
#include <regex>
#include <string>
void show_matches(const std::string& in, const std::string& re)
{
    std::smatch m;
    std::regex_search(in, m, std::regex(re));
    if (!m.empty())
    {
        std::cout << "input=[" << in << "], regex=[" << re << "]\n  "
                     "prefix=[" << m.prefix() << "]\n  smatch: ";
        for (std::size_t n = 0; n < m.size(); ++n)
            std::cout << "m[" << n << "]=[" << m[n] << "] ";
        std::cout << "\n  suffix=[" << m.suffix() << "]\n";
    }
    else
        std::cout << "input=[" << in << "], regex=[" << re << "]: NO MATCH\n";
}
int main()
{
    // findet das a am Ende der Eingabe
    show_matches("aaa", "a$");
    // findet das o am Ende des ersten Wortes
    show_matches("moo goo gai pan", "o\\b");
    // die Lookahead-Expression findet die leere Zeichenkette direkt nach dem ersten b
    // dies füllt m[1] mit "aaa", obwohl m[0] leer ist
    show_matches("baaabac", "(?=(a+))");
    // weil Backtracking in Lookaheads verboten ist,
    // findet dies aba statt aaaba
    show_matches("baaabac", "(?=(a+))a*b\\1");
    // logisches UND via Lookahead: dieses Passwort stimmt überein, WENN es
    // mindestens einen Kleinbuchstaben
    // UND mindestens einen Großbuchstaben
    // UND mindestens ein Satzzeichen enthält
    // UND mindestens 6 Zeichen lang ist
    show_matches("abcdef", "(?=.*[[:lower:]])(?=.*[[:upper:]])(?=.*[[:punct:]]).{6,}");
    show_matches("aB,def", "(?=.*[[:lower:]])(?=.*[[:upper:]])(?=.*[[:punct:]]).{6,}");
}

Ausgabe:

input=[aaa], regex=[a$]
  prefix=[aa]
  smatch: m[0]=[a] 
  suffix=[]
input=[moo goo gai pan], regex=[o\b]
  prefix=[mo]
  smatch: m[0]=[o] 
  suffix=[ goo gai pan]
input=[baaabac], regex=[(?=(a+))]
  prefix=[b]
  smatch: m[0]=[] m[1]=[aaa] 
  suffix=[aaabac]
input=[baaabac], regex=[(?=(a+))a*b\1]
  prefix=[baa]
  smatch: m[0]=[aba] m[1]=[a] 
  suffix=[c]
input=[abcdef], regex=[(?=.*[[:lower:]])(?=.*[[:upper:]])(?=.*[[:punct:]]).{6,}]: NO MATCH
input=[aB,def], regex=[(?=.*[[:lower:]])(?=.*[[:upper:]])(?=.*[[:punct:]]).{6,}]
  prefix=[]
  smatch: m[0]=[aB,def] 
  suffix=[]

Atome

Ein Atom kann eines der folgenden sein:

Atom ::

PatternCharacter
.
\ AtomEscape
CharacterClass
( Disjunction )
( ? : Disjunction )

wo AtomEscape ::

DezimalEscape
ZeichenEscape
ZeichenklassenEscape

Verschiedene Arten von Atomen werden unterschiedlich ausgewertet.

Teilausdrücke

Das Atom ( Disjunktion ) ist ein markierter Teilausdruck: Es führt die Disjunktion aus und speichert die Kopie der Eingabe-Teilzeichenkette, die von der Disjunktion konsumiert wurde, im Submatch-Array an dem Index, der der Anzahl der bisher im gesamten regulären Ausdruck angetroffenen linken öffnenden Klammern ( markierter Teilausdrücke entspricht.

Neben der Rückgabe in std::match_results sind die erfassten Submatches als Backreferences ( \1 , \2 , ...) zugänglich und können in regulären Ausdrücken referenziert werden. Beachten Sie, dass std::regex_replace $ anstelle von \ für Backreferences verwendet ( $1 , $2 , ...), analog zu String.prototype.replace (ECMA-262, Abschnitt 15.5.4.11).

Das Atom ( ? : Disjunction ) (nicht-markierender Teilausdruck) wertet einfach die Disjunction aus und speichert ihre Ergebnisse nicht im Submatch. Dies ist eine rein lexikalische Gruppierung.

Backreferenzen

DecimalEscape ::

DecimalIntegerLiteral [ lookahead DecimalDigit ]

Wenn \ von einer Dezimalzahl N gefolgt wird, deren erste Ziffer nicht 0 ist, dann wird die Escape-Sequenz als Backreference betrachtet. Der Wert N wird durch Aufruf von std::regex_traits::value (nur C++) auf jede der Ziffern erhalten und durch Kombination ihrer Ergebnisse unter Verwendung von Basis-10-Arithmetik. Es ist ein Fehler, wenn N größer ist als die Gesamtanzahl der linken erfassenden Klammern im gesamten regulären Ausdruck.

Wenn ein Backreference \N als ein Atom erscheint, matcht es dieselbe Teilzeichenkette, die aktuell im N-ten Element des Submatch-Arrays gespeichert ist.

Die dezimale Escape-Sequenz \0 ist KEINE Rückreferenz: Es handelt sich um eine Zeichen-Escape-Sequenz, die das NUL -Zeichen repräsentiert. Ihr darf keine dezimale Ziffer folgen.

Wie oben erwähnt, beachten Sie, dass std::regex_replace für Backreferences ( $1 , $2 , ...) $ anstelle von \ verwendet.

Einzelzeichen-Übereinstimmungen

Das Atom . erkennt und konsumiert ein beliebiges Zeichen aus der Eingabezeichenkette mit Ausnahme von LineTerminator ( U+000D , U+000A , U+2029 , oder U+2028 )

Das Atom PatternCharacter , wobei PatternCharacter ein beliebiges SourceCharacter AUSSER den Zeichen ^ $ \ . * + ? ( ) [ ] { } | ist, gleicht ein Zeichen aus der Eingabe ab und konsumiert es, wenn es diesem PatternCharacter entspricht.

Die Gleichheit für dieses und alle anderen Einzelzeichen-Übereinstimmungen ist wie folgt definiert:

1) Wenn std::regex_constants::icase gesetzt ist, sind die Zeichen gleich, wenn die Rückgabewerte von std::regex_traits::translate_nocase gleich sind (Nur C++) .
2) Andernfalls, wenn std::regex_constants::collate gesetzt ist, sind die Zeichen gleich, wenn die Rückgabewerte von std::regex_traits::translate gleich sind (Nur C++) .
3) Andernfalls sind die Zeichen gleich, wenn operator == true zurückgibt.

Jedes Atom , das aus dem Escape-Zeichen \ gefolgt von CharacterEscape besteht, sowie das spezielle DecimalEscape \0 , findet eine Übereinstimmung und verbraucht ein Zeichen aus der Eingabe, wenn es gleich dem durch die CharacterEscape dargestellten Zeichen ist. Die folgenden Zeichen-Escape-Sequenzen werden erkannt:

CharacterEscape ::

ControlEscape
c ControlLetter
HexEscapeSequence
UnicodeEscapeSequence
IdentityEscape

Hier ist ControlEscape eines der folgenden fünf Zeichen: f n r t v

ControlEscape Code Unit Name
f U+000C Seitenvorschub
n U+000A Zeilenvorschub
r U+000D Wagenrücklauf
t U+0009 horizontaler Tabulator
v U+000B vertikaler Tabulator

ControlLetter ist ein beliebiger Klein- oder Großbuchstabe im ASCII-Zeichensatz, und diese Steuerzeichen-Escape-Sequenz entspricht dem Zeichen, dessen Codeeinheit gleich dem Rest der Division des Werts der Codeeinheit von ControlLetter durch 32 ist. Zum Beispiel entsprechen sowohl \cD als auch \cd der Codeeinheit U+0004 (EOT), da 'D' U+0044 ist und 0x44 % 32 == 4 , und 'd' U+0064 ist und 0x64 % 32 == 4 .

HexEscapeSequence ist der Buchstabe x gefolgt von genau zwei HexDigit s (wobei HexDigit eines von 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F ist). Diese Zeichen-Escape-Sequenz entspricht dem Zeichen, dessen Code-Einheit dem numerischen Wert der zweistelligen Hexadezimalzahl entspricht.

UnicodeEscapeSequence ist der Buchstabe u gefolgt von genau vier HexDigit s. Diese Zeichen-Escape-Sequenz entspricht dem Zeichen, dessen Code-Einheit dem numerischen Wert dieser vierstelligen Hexadezimalzahl entspricht. Wenn der Wert nicht in den std::basic_regex -Typ CharT passt, wird std::regex_error geworfen (nur C++) .

IdentityEscape kann ein beliebiges nicht-alphanumerisches Zeichen sein: zum Beispiel ein weiterer Backslash. Es entspricht dem Zeichen unverändert.

#include <cstddef>
#include <iostream>
#include <regex>
#include <string>
void show_matches(const std::wstring& in, const std::wstring& re)
{
    std::wsmatch m;
    std::regex_search(in, m, std::wregex(re));
    if (!m.empty())
    {
        std::wcout << L"input=[" << in << L"], regex=[" << re << L"]\n  "
                      L"prefix=[" << m.prefix() << L"]\n  wsmatch: ";
        for (std::size_t n = 0; n < m.size(); ++n)
            std::wcout << L"m[" << n << L"]=[" << m[n] << L"] ";
        std::wcout << L"\n  suffix=[" << m.suffix() << L"]\n";
    }
    else
        std::wcout << L"input=[" << in << "], regex=[" << re << L"]: NO MATCH\n";
}
int main()
{
    // Die meisten Escape-Sequenzen ähneln C++, außer bei Metazeichen. Sie müssen
    // entweder doppelt escapen oder Raw-Strings für die Schrägstriche verwenden.
    show_matches(L"C++\\", LR"(C\+\+\\)");
    // Escape-Sequenzen und NUL.
    std::wstring s(L"ab\xff\0cd", 5);
    show_matches(s, L"(\\0|\\u00ff)");
    // Für Nicht-BMP-Unicode ist keine Übereinstimmung definiert, da ECMAScript UTF-16
    // Atome verwendet. Ob dieses Emoji-Banane übereinstimmt, kann plattformabhängig sein:
    // Dies müssen Wide-Strings sein!
    show_matches(L"\U0001f34c", L"[\\u0000-\\ufffe]+");
}

Mögliche Ausgabe:

input=[C++\], regex=[C\+\+\\]
  prefix=[]
  wsmatch: m[0]=[C++\]
  suffix=[]
input=[ab?c], regex=[(\0{{!}}\u00ff)]
  prefix=[ab]
  wsmatch: m[0]=[?] m[1]=[?]
  suffix=[c]
input=[?], regex=[[\u0000-\ufffe]+]: NO MATCH

Zeichenklassen

Ein Atom kann eine Zeichenklasse repräsentieren, das heißt, es wird ein Zeichen finden und verarbeiten, wenn es zu einer der vordefinierten Gruppen von Zeichen gehört.

Eine Zeichenklasse kann durch eine Zeichenklassen-Escape-Sequenz eingeführt werden:

Atom ::

\ Zeichenklassen-Escape

oder direkt

Atom ::

Zeichenklasse

Die Zeichenklassen-Escapes sind Kurzformen für einige der gebräuchlichen Zeichenklassen, wie folgt:

CharacterClassEscape ClassName expression (C++ only) Bedeutung
d [[:digit:]] Ziffern
D [^[:digit:]] Nicht-Ziffern
s [[:space:]] Leerzeichenzeichen
S [^[:space:]] Nicht-Leerzeichenzeichen
w [_[:alnum:]] Alphanumerische Zeichen und das Zeichen _
W [^_[:alnum:]] Zeichen außer alphanumerischen oder _
Die genaue Bedeutung jedes dieser Zeichenklassen-Escapes in C++ wird durch die gebietsschemaabhängigen benannten Zeichenklassen definiert und nicht durch explizites Auflisten der zulässigen Zeichen wie in ECMAScript.

Eine CharacterClass ist eine in Klammern eingeschlossene Sequenz von ClassRanges , die optional mit dem Negationsoperator ^ beginnt. Wenn sie mit ^ beginnt, passt dieses Atom auf jedes Zeichen, das NICHT in der Menge der Zeichen enthalten ist, die durch die Vereinigung aller ClassRanges repräsentiert wird. Andernfalls passt dieses Atom auf jedes Zeichen, das in der Menge der Zeichen enthalten ist, die durch die Vereinigung aller ClassRanges repräsentiert wird.

CharacterClass ::

[ [ lookahead ∉ { ^ }] ClassRanges ]
[ ^ ClassRanges ]

ClassRanges ::

[leer]
NonemptyClassRanges

NonemptyClassRanges ::

ClassAtom
ClassAtom NonemptyClassRangesNoDash
ClassAtom - ClassAtom ClassRanges

Wenn ein nicht-leerer Klassenbereich die Form ClassAtom - ClassAtom hat, entspricht er jedem Zeichen aus einem Bereich, der wie folgt definiert ist: (Nur C++)

Das erste ClassAtom muss auf ein einzelnes Sortierelement c1 passen und das zweite ClassAtom muss auf ein einzelnes Sortierelement c2 passen. Um zu prüfen, ob das Eingabezeichen c von dieser Range erfasst wird, werden folgende Schritte unternommen:

1) Wenn std::regex_constants::collate nicht aktiviert ist, wird das Zeichen durch direkten Vergleich der Codepunkte gematcht: c wird gematcht, wenn c1 <= c && c <= c2
1) Andernfalls (wenn std::regex_constants::collate aktiviert ist):
1) Wenn std::regex_constants::icase aktiviert ist, werden alle drei Zeichen ( c , c1 und c2 ) an std::regex_traits::translate_nocase übergeben
2) Andernfalls (wenn std::regex_constants::icase nicht gesetzt ist), werden alle drei Zeichen ( c , c1 , und c2 ) an std::regex_traits::translate übergeben
2) Die resultierenden Zeichenketten werden mit std::regex_traits::transform verglichen und das Zeichen c wird gematcht, wenn transformed c1 <= transformed c && transformed c <= transformed c2

Das Zeichen - wird wörtlich behandelt, wenn es

  • das erste oder letzte Zeichen von ClassRanges
  • das erste oder letzte ClassAtom einer durch Bindestrich getrennten Bereichsangabe
  • unmittelbar nach einer durch Bindestrich getrennten Bereichsangabe folgt
  • mit einem Backslash als CharacterEscape maskiert

NonemptyClassRangesNoDash ::

ClassAtom
ClassAtomNoDash NonemptyClassRangesNoDash
ClassAtomNoDash - ClassAtom ClassRanges

ClassAtom ::

-
ClassAtomNoDash
ClassAtomExClass (nur C++)
ClassAtomCollatingElement (nur C++)
ClassAtomEquivalence (nur C++)

ClassAtomNoDash ::

SourceCharacter aber nicht eines von \ oder ] oder -
\ ClassEscape

Jedes ClassAtomNoDash repräsentiert ein einzelnes Zeichen – entweder SourceCharacter unverändert oder wie folgt escaped:

ClassEscape ::

DezimalEscape
b
ZeichenEscape
ZeichenklassenEscape

Das spezielle ClassEscape \b erzeugt einen Zeichensatz, der der Codeeinheit U+0008 (Rücktaste) entspricht. Außerhalb einer CharacterClass handelt es sich um die Assertion für Wortgrenzen.

Die Verwendung von \B und die Verwendung jeglicher Rückreferenz ( DecimalEscape außer Null) innerhalb einer CharacterClass ist ein Fehler.

Die Zeichen - und ] müssen in einigen Situationen escaped werden, um als Atome behandelt zu werden. Andere Zeichen mit spezieller Bedeutung außerhalb von CharacterClass , wie * oder ? , müssen nicht escaped werden.

POSIX-basierte Zeichenklassen

Diese Zeichenklassen sind eine Erweiterung der ECMAScript-Grammatik und entsprechen den Zeichenklassen, die in den POSIX-Regulären Ausdrücken zu finden sind.

ClassAtomExClass (Nur C++) ::

[: ClassName :]

Repräsentiert alle Zeichen, die Mitglieder der benannten Zeichenklasse ClassName sind. Der Name ist nur gültig, wenn std::regex_traits::lookup_classname für diesen Namen einen Wert ungleich Null zurückgibt. Wie in std::regex_traits::lookup_classname beschrieben, sind die folgenden Namen garantiert erkennbar: alnum, alpha, blank, cntrl, digit, graph, lower, print, punct, space, upper, xdigit, d, s, w . Zusätzliche Namen können durch systemseitig bereitgestellte Locales (wie jdigit oder jkanji im Japanischen) bereitgestellt oder als benutzerdefinierte Erweiterung implementiert werden.

ClassAtomCollatingElement (Nur C++) ::

[. ClassName .]

Repräsentiert das benannte Kollationselement, das entweder ein einzelnes Zeichen oder eine Zeichenfolge darstellen kann, die unter der eingestellten Locale als eine einzelne Einheit kollationiert, wie z.B. [.tilde.] oder [.ch.] im Tschechischen. Der Name ist nur gültig, wenn std::regex_traits::lookup_collatename kein leerer String ist.

Bei Verwendung von std::regex_constants::collate können Kollationselemente immer als Endpunkte eines Bereichs verwendet werden (z.B. [[.dz.]-g] im Ungarischen).

ClassAtomEquivalence (Nur C++) ::

[= ClassName =]

Repräsentiert alle Zeichen, die Mitglieder derselben Äquivalenzklasse wie das benannte Kollatierungselement sind, das heißt alle Zeichen, deren primärer Kollationsschlüssel derselbe ist wie der für das Kollatierungselement ClassName . Der Name ist nur gültig, wenn std::regex_traits::lookup_collatename für diesen Namen keine leere Zeichenkette zurückgibt und wenn der von std::regex_traits::transform_primary für das Ergebnis des Aufrufs von std::regex_traits::lookup_collatename zurückgegebene Wert keine leere Zeichenkette ist.

Ein primärer Sortierschlüssel ist einer, der Groß-/Kleinschreibung, Akzentuierung oder localespezifische Anpassungen ignoriert; so entspricht beispielsweise [[=a=]] jedem der Zeichen: a, À, Á, Â, Ã, Ä, Å, A, à, á, â, ã, ä and å.

ClassName (nur C++) ::

KlassennameZeichen
KlassennameZeichen ClassName

ClassNameCharacter (nur C++) ::

SourceCharacter aber nicht eines von . = :