Zeichenklasse: [...], [^...]

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.

Eine Zeichenklasse stimmt mit jedem Zeichen innerhalb oder außerhalb einer benutzerdefinierten Zeichenmenge überein. Wenn das v-Flag aktiviert ist, kann es auch verwendet werden, um Zeichenfolgen von endlicher Länge zu matchen.

Syntax

regex
[]
[abc]
[A-Z]

[^]
[^abc]
[^A-Z]

// `v` mode only
[operand1&&operand2]
[operand1--operand2]
[\q{substring}]

Parameter

operand1, operand2

Kann ein einzelnes Zeichen, eine andere in eckige Klammern eingeschlossene Zeichenklasse, ein Zeichenklassen-Escape, ein Unicode-Zeichenklassen-Escape oder eine Zeichenkette mit der \q-Syntax sein.

substring

Eine literale Zeichenkette.

Beschreibung

Eine Zeichenklasse gibt eine Liste von Zeichen zwischen eckigen Klammern an und stimmt mit jedem Zeichen in der Liste überein. Das v-Flag verändert drastisch die Art und Weise, wie Zeichenklassen geparst und interpretiert werden. Die folgenden Syntaxen sind sowohl im v-Modus als auch im Nicht-v-Modus verfügbar:

  • Ein einzelnes Zeichen: stimmt mit dem Zeichen selbst überein.
  • Ein Bereich von Zeichen: stimmt mit jedem Zeichen im eingeschlossenen Bereich überein. Der Bereich wird durch zwei Zeichen angegeben, die durch einen Bindestrich (-) getrennt sind. Das erste Zeichen muss im Zeichenwert kleiner sein als das zweite Zeichen. Der Zeichenwert ist der Unicode-Codepunkt des Zeichens. Da Unicode-Codepunkte üblicherweise Alphabete in Reihenfolge zuordnen, spezifiziert [a-z] alle Kleinbuchstaben des lateinischen Alphabets, während [α-ω] alle Kleinbuchstaben des griechischen Alphabets spezifiziert. Im Unicode-unbewussten Modus werden Regexe als Sequenz von BMP-Zeichen interpretiert. Daher stellen Surrogatpaare in Zeichenklassen zwei Zeichen anstelle von einem dar; siehe unten für Details.
  • Escape-Sequenzen: \b, \-, Zeichenklassen-Escapes, Unicode-Zeichenklassen-Escapes und andere Zeichen-Escapes.

Diese Syntaxen können beliebig oft vorkommen, und die von ihnen dargestellten Zeichensätze werden vereinigt. Zum Beispiel stimmt /[a-zA-Z0-9]/ mit jedem Buchstaben oder Ziffer überein.

Das ^-Präfix in einer Zeichenklasse erstellt eine Komplementklasse. Zum Beispiel stimmt [^abc] mit jedem Zeichen außer a, b oder c überein. Das ^-Zeichen ist ein literales Zeichen, wenn es in der Mitte einer Zeichenklasse erscheint — zum Beispiel stimmt [a^b] mit den Zeichen a, ^ und b überein.

Die lexikalische Grammatik führt eine sehr grobe Analyse der Regex-Literale durch, damit das Regex-Literal nicht am /-Zeichen endet, das innerhalb einer Zeichenklasse erscheint. Das bedeutet, dass /[/]/ gültig ist, ohne dass das / entkommen werden muss.

Die Grenzen eines Zeichenbereichs dürfen nicht mehr als ein Zeichen angeben, was passiert, wenn Sie ein Zeichenklassen-Escape verwenden. Zum Beispiel:

js
/[\s-9]/u; // SyntaxError: Invalid regular expression: Invalid character class

Im Unicode-unbewussten Modus werden Zeichenbereiche, bei denen eine Grenze eine Zeichenklasse ist, dazu führen, dass - ein literales Zeichen wird. Dies ist eine veraltete Syntax zur Web-Kompatibilität, und Sie sollten sich nicht darauf verlassen.

js
/[\s-9]/.test("-"); // true

Im Unicode-unbewussten Modus werden Regexe als eine Sequenz von BMP-Zeichen interpretiert. Daher stellen Surrogatpaare in Zeichenklassen zwei Zeichen anstelle von einem dar.

js
/[😄]/.test("\ud83d"); // true
/[😄]/u.test("\ud83d"); // false

/[😄-😛]/.test("😑"); // SyntaxError: Invalid regular expression: /[😄-😛]/: Range out of order in character class
/[😄-😛]/u.test("😑"); // true

Selbst wenn das Muster die Groß-/Kleinschreibung ignoriert, ist die Groß-/Kleinschreibung der beiden Enden eines Bereichs entscheidend dafür, welche Zeichen zum Bereich gehören. Zum Beispiel stimmt das Muster /[E-F]/i nur mit E, F, e und f überein, während das Muster /[E-f]/i mit allen Groß- und Kleinbuchstaben des ASCII-Zeichensatzes (weil es über E–Z und a–f spannt) übereinstimmt, sowie mit [, \, ], ^, _ und `.

Nicht-v-Modus-Zeichenklasse

Nicht-v-Modus-Zeichenklassen interpretieren die meisten Zeichen wörtlich und haben weniger Einschränkungen hinsichtlich der Zeichen, die sie enthalten können. Zum Beispiel ist . das wörtliche Punktzeichen, nicht der Platzhalter. Die einzigen Zeichen, die nicht wörtlich erscheinen dürfen, sind \, ] und -.

  • In Zeichenklassen werden die meisten Escape-Sequenzen unterstützt, außer \b, \B und Rückverweise. \b gibt ein Rückschrittzeichen anstelle einer Wortgrenze an, während die anderen beiden Syntaxfehler verursachen. Um \ wörtlich zu verwenden, entkommen Sie es als \\.
  • Das ]-Zeichen zeigt das Ende der Zeichenklasse an. Um es wörtlich zu verwenden, entkommen Sie es als \].
  • Das Bindestrich (-)-Zeichen zeigt, wenn es zwischen zwei Zeichen verwendet wird, einen Bereich an. Wenn es am Anfang oder Ende einer Zeichenklasse erscheint, ist es ein wörtliches Zeichen. Es ist auch ein wörtliches Zeichen, wenn es in den Grenzen eines Bereichs verwendet wird. Zum Beispiel stimmt [a-] mit den Zeichen a und -, [!--] stimmt mit den Zeichen ! bis -, und [--9] stimmt mit den Zeichen - bis 9 überein. Sie können es auch als \- entkommen, wenn Sie es irgendwo wörtlich verwenden möchten.

v-Modus-Zeichenklasse

Die Grundidee von Zeichenklassen im v-Modus bleibt die gleiche: Sie können immer noch die meisten Zeichen wörtlich verwenden, - verwenden, um Zeichenbereiche anzugeben, und Escape-Sequenzen verwenden. Eines der wichtigsten Merkmale des v-Flags ist die Mengennotation innerhalb von Zeichenklassen. Wie bereits erwähnt, können normale Zeichenklassen Vereinigungen durch die Verkettung von zwei Bereichen ausdrücken, wie zum Beispiel die Verwendung von [A-Z0-9], um "die Vereinigung der Menge [A-Z] und der Menge [0-9]" zu bedeuten. Es gibt jedoch keinen einfachen Weg, andere Operationen mit Zeichensätzen darzustellen, wie z. B. Schnittmenge und Differenz.

Mit dem v-Flag wird die Schnittmenge mit && und die Subtraktion mit -- ausgedrückt. Das Fehlen von beidem impliziert Vereinigung. Die beiden Operanden von && oder -- können ein Zeichen, ein Zeichen-Escape, ein Zeichenklassen-Escape oder sogar eine andere Zeichenklasse sein. Zum Beispiel, um "ein Wortzeichen, das kein Unterstrich ist" auszudrücken, können Sie [\w--_] verwenden. Sie können Operatoren nicht auf derselben Ebene mischen. Zum Beispiel ist [\w&&[A-z]--_] ein Syntaxfehler. Da Sie jedoch Zeichenklassen verschachteln können, können Sie explizit schreiben [\w&&[[A-z]--_]] oder [[\w&&[A-z]]--_] (was beides [A-Za-z] bedeutet). Ebenso ist [AB--C] ungültig, und Sie müssen schreiben [A[B--C]] (was einfach [AB] bedeutet).

Im v-Modus kann das Unicode-Zeichenklassen-Escape \p mit Zeichenketten von endlicher Länge wie Emojis übereinstimmen. Aus Symmetriegründen können reguläre Zeichenklassen auch mehr als ein Zeichen übereinstimmen. Um in einer Zeichenklasse ein "Zeichenkettenliteraler" zu schreiben, umschließen Sie die Zeichenkette mit \q{...}. Die einzige in \q unterstützte Regex-Syntax ist Disjunktion — abgesehen davon muss \q Literale vollständig umschließen (einschließlich entkommener Zeichen). Dies gewährleistet, dass Zeichenklassen nur mit Zeichenketten von endlicher Länge mit endlich vielen Möglichkeiten übereinstimmen können.

Da die Syntax der Zeichenklasse nun ausgefeilter ist, sind mehr Zeichen reserviert und dürfen nicht wörtlich erscheinen.

  • Zusätzlich zu ] und \ müssen die folgenden Zeichen in Zeichenklassen entkommen werden, wenn sie wörtliche Zeichen darstellen: (, ), [, {, }, /, -, |. Diese Liste ist der Liste der Syntaxzeichen etwas ähnlich, außer dass ^, $, *, + und ? innerhalb von Zeichenklassen nicht reserviert sind, während / und - außerhalb von Zeichenklassen nicht reserviert sind (obwohl / ein Regex-Literal abgrenzen kann und daher immer noch entkommen werden muss). Alle diese Zeichen können in u-Modus-Zeichenklassen auch optional entkommen werden.
  • Die folgenden "doppelten Interpunktionszeichen"-Sequenzen müssen ebenfalls entkommen werden (aber sie machen ohne das v-Flag sowieso wenig Sinn): &&, !!, ##, $$, %%, **, ++, ,,, .., ::, ;;, <<, ==, >>, ??, @@, ^^, ``, ~~. Im u-Modus können einige dieser Zeichen nur wörtlich innerhalb von Zeichenklassen erscheinen und führen zu einem Syntaxfehler, wenn sie entkommen werden. Im v-Modus müssen sie entkommen werden, wenn sie paarweise erscheinen, können aber optional entkommen werden, wenn sie einzeln erscheinen. Zum Beispiel ist /[\!]/u ungültig, weil es sich um einen Identitäts-Escape handelt, aber sowohl /[\!]/v als auch /[!]/v sind gültig, während /[!!]/v ungültig ist. Die Buchstaben-Referenz hat eine detaillierte Tabelle, welche Zeichen entkommen oder unentkommen erscheinen können.

Komplement-Zeichenklassen [^...] können nicht mit Zeichenfolgen matchen, die länger als ein Zeichen sind. Zum Beispiel ist [\q{ab|c}] gültig und stimmt mit der Zeichenfolge "ab" überein, aber [^\q{ab|c}] ist ungültig, weil unklar ist, wie viele Zeichen konsumiert werden sollen. Die Überprüfung erfolgt, indem geprüft wird, ob alle \q einzelne Zeichen enthalten und alle \p Zeichenattribute angeben — für Vereinigungen müssen alle Operanden rein Zeichen sein; für Schnittmengen muss mindestens ein Operand rein Zeichen sein; für Subtraktionen muss der linkeste Operand rein Zeichen sein. Die Überprüfung ist syntaktisch ohne Berücksichtigung des tatsächlich angegebenen Zeichensatzes, was bedeutet, dass obwohl /[^\q{ab|c}--\q{ab}]/v gleichwertig mit /[^c]/v ist, es dennoch abgelehnt wird.

Komplementklassen und groß-/kleinschreibungsunabhängiges Matching

Im Nicht-v-Modus werden Komplement-Zeichenklassen [^...] einfach durch Invertieren des Matchergebnisses implementiert — das heißt, [^...] stimmt, wenn [...] nicht übereinstimmt, und umgekehrt. Die anderen Komplementklassen, wie \P{...} und \W, arbeiten durch die eifrige Konstruktion der Menge, die aus allen Zeichen ohne die angegebene Eigenschaft besteht. Sie scheinen dasselbe Verhalten zu erzeugen, sind jedoch komplexer, wenn sie mit groß-/kleinschreibungsunabhängigem Matching kombiniert werden.

Betrachten Sie die folgenden zwei Regexe:

js
const r1 = /\p{Lowercase_Letter}/iu;
const r2 = /[^\P{Lowercase_Letter}]/iu;

Das r2 ist eine doppelte Verneinung und scheint mit r1 gleichwertig zu sein. Tatsächlich stimmt r1 jedoch mit allen Groß- und Kleinbuchstaben des ASCII-Zeichensatzes überein, während r2 mit keinem übereinstimmt. Um zu veranschaulichen, wie es funktioniert, stellen Sie sich vor, dass wir nur mit ASCII-Zeichen arbeiten, nicht mit dem gesamten Unicode-Zeichensatz, und r1 und r2 wie unten angegeben sind:

js
const r1 = /[a-z]/iu;
const r2 = /[^A-Z]/iu;

Denken Sie daran, dass die groß-/kleinschreibungsunabhängige Übereinstimmung durch das Falten sowohl des Musters als auch der Eingabe auf dieselbe Groß-/Kleinschreibung erfolgt (siehe ignoreCase für weitere Details). Für r1 bleibt die Zeichenklasse a-z nach dem Groß-/Kleinschreibungsfalten dieselbe, während sowohl Groß- als auch Kleinbuchstaben-ASCII-Zeichenketteneingaben auf Kleinbuchstaben gefaltet werden, sodass r1 sowohl "A" als auch "a" übereinstimmen kann. Für r2 wird die Zeichenklasse A-Z auf a-z gefaltet; jedoch negiert ^ das Matchergebnis, sodass [^A-Z] effektiv nur mit Großbuchstabenzeichen übereinstimmt. Beide ASCII-Zeichenketteneingaben werden jedoch immer noch auf Kleinbuchstaben gefaltet, wodurch r2 nichts übereinstimmt.

Im v-Modus wird dieses Verhalten behoben — [^...] konstruiert ebenfalls eifrig die Komplementklasse anstelle des Invertierens des Matchergebnisses. Dies macht [^\P{Lowercase_Letter}] und \p{Lowercase_Letter} strikt gleichwertig.

Beispiele

Hexadezimalziffern matchen

Die folgende Funktion bestimmt, ob eine Zeichenkette eine gültige Hexadezimalzahl enthält:

js
function isHexadecimal(str) {
  return /^[0-9A-F]+$/i.test(str);
}

isHexadecimal("2F3"); // true
isHexadecimal("beef"); // true
isHexadecimal("undefined"); // false

Verwendung von Schnittmengen

Die folgende Funktion matcht griechische Buchstaben.

js
function greekLetters(str) {
  return str.match(/[\p{Script_Extensions=Greek}&&\p{Letter}]/gv);
}

// 𐆊 is U+1018A GREEK ZERO SIGN
greekLetters("π𐆊P0零αAΣ"); // [ 'π', 'α', 'Σ' ]

Verwendung von Subtraktionen

Die folgende Funktion matcht alle nicht-ASCII-Zahlen.

js
function nonASCIINumbers(str) {
  return str.match(/[\p{Decimal_Number}--[0-9]]/gv);
}

// 𑜹 is U+11739 AHOM DIGIT NINE
nonASCIINumbers("𐆊0零1𝟜𑜹a"); // [ '𝟜', '𑜹' ]

Zeichenfolgen matchen

Die folgende Funktion stimmt mit allen Zeilenendesequenzen überein, einschließlich der Zeilenendzeichen und der Sequenz \r\n (CRLF).

js
function getLineTerminators(str) {
  return str.match(/[\r\n\u2028\u2029\q{\r\n}]/gv);
}

getLineTerminators(`
A poem\r
Is split\r\n
Into many
Stanzas
`); // [ '\r', '\r\n', '\n' ]

Dieses Beispiel ist genau äquivalent zu /(?:\r|\n|\u2028|\u2029|\r\n)/gu oder /(?:[\r\n\u2028\u2029]|\r\n)/gu, nur kürzer.

Der nützlichste Fall von \q{} ist, wenn man Subtraktionen und Schnittmengen durchführt. Dies war zuvor mit mehrfachen Lookaheads möglich. Die folgende Funktion stimmt mit Flaggen überein, die nicht zu den amerikanischen, chinesischen, russischen, britischen und französischen Flaggen gehören.

js
function notUNSCPermanentMember(flag) {
  return /^[\p{RGI_Emoji_Flag_Sequence}--\q{🇺🇸|🇨🇳|🇷🇺|🇬🇧|🇫🇷}]$/v.test(flag);
}

notUNSCPermanentMember("🇺🇸"); // false
notUNSCPermanentMember("🇩🇪"); // true

Dieses Beispiel ist größtenteils äquivalent zu /^(?!🇺🇸|🇨🇳|🇷🇺|🇬🇧|🇫🇷)\p{RGI_Emoji_Flag_Sequence}$/v, möglicherweise jedoch leistungsfähiger.

Spezifikationen

Specification
ECMAScript Language Specification
# prod-CharacterClass

Browser-Kompatibilität

BCD tables only load in the browser

Siehe auch