Anstehende Funktionen für reguläre Ausdrücke

Jakob Gruber
Yang Guo

Mit ES2015 wurden der JavaScript-Sprache viele neue Funktionen hinzugefügt, darunter erhebliche Verbesserungen der Syntax für reguläre Ausdrücke mit den Unicode-Flags (/u) und den fixierten Flags (/y). Seitdem ist die Entwicklung jedoch nicht aufgehört. In enger Zusammenarbeit mit anderen Mitgliedern von TC39 (der ECMAScript-Standardsgremium) hat das V8-Team mehrere neue Funktionen vorgeschlagen und gemeinsam entwickelt, um reguläre Ausdrücke noch leistungsfähiger zu machen.

Diese Funktionen werden derzeit zur Aufnahme in die JavaScript-Spezifikation vorgeschlagen. Obwohl die Angebote noch nicht vollständig angenommen wurden, befinden sie sich bereits in Phase 3 des TC39-Prozesses. Wir haben diese Funktionen hinter einer Kennzeichnung implementiert (siehe unten), um den jeweiligen Verfassern des Vorschlags rechtzeitig Feedback zur Entwicklung und Implementierung geben zu können, bevor die Spezifikation endgültig festgelegt wurde.

In diesem Blogpost erhalten Sie einen Ausblick auf diese spannende Zukunft. Wenn Sie den nächsten Beispielen folgen möchten, aktivieren Sie experimentelle JavaScript-Funktionen unter chrome://flags/#enable-javascript-harmony.

Benannte Aufnahmen

Reguläre Ausdrücke können sogenannte Erfassungen (oder Gruppen) enthalten, mit denen ein Teil des übereinstimmenden Texts erfasst werden kann. Bisher konnten Entwickler sich nur anhand ihres Index auf diese Aufnahmen beziehen, der durch die Position der Erfassung innerhalb des Musters bestimmt wird.

const pattern = /(\d{4})-(\d{2})-(\d{2})/u;
const result = pattern.exec('2017-07-10');
// result[0] === '2017-07-10'
// result[1] === '2017'
// result[2] === '07'
// result[3] === '10'

Aber reguläre Ausdrücke sind bereits bekanntermaßen schwer zu lesen, zu schreiben und zu pflegen, und numerische Verweise können weitere Komplikationen verursachen. Bei längeren Mustern kann es beispielsweise schwierig sein, den Index einer bestimmten Aufnahme zu ermitteln:

/(?:(.)(.(?<=[^(])(.)))/  // Index of the last capture?

Noch schlimmer ist es, wenn Änderungen an einem Muster die Indizes aller vorhandenen Erfassungen verschieben:

/(a)(b)(c)\3\2\1/     // A few simple numbered backreferences.
/(.)(a)(b)(c)\4\3\2/  // All need to be updated.

Benannte Aufnahmen sind ein neues Feature, mit dem diese Probleme gemindert werden können, da Entwickler damit Aufnahmen Namen zuweisen können. Die Syntax ähnelt Perl, Java, .Net und Ruby:

const pattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
const result = pattern.exec('2017-07-10');
// result.groups.year === '2017'
// result.groups.month === '07'
// result.groups.day === '10'

Auf benannte Aufnahmen kann auch durch benannte Rückverweise und über String.prototype.replace verwiesen werden:

// Named backreferences.
/(?<LowerCaseX>x)y\k<LowerCaseX>/.test('xyx');  // true

// String replacement.
const pattern = /(?<fst>a)(?<snd>b)/;
'ab'.replace(pattern, '$<snd>$<fst>');                              // 'ba'
'ab'.replace(pattern, (m, p1, p2, o, s, {fst, snd}) => fst + snd);  // 'ba'

Alle Details zu dieser neuen Funktion finden Sie im Spezifikationsvorschlag.

PunktAll-Flag

Standardmäßig entspricht das Atom . in regulären Ausdrücken jedem Zeichen mit Ausnahme von Zeilenabschlusszeichen:

/foo.bar/u.test('foo\nbar');   // false

Ein Angebot führt den „dotAll“-Modus ein, der über das Flag /s aktiviert wird. Im „dotAll-Modus“ stimmt . auch mit Zeilenabschlusszeichen überein.

/foo.bar/su.test('foo\nbar');  // true

Alle Details zu dieser neuen Funktion finden Sie im Spezifikationsvorschlag.

Unicode-Escapezeichen für Eigenschaften

Seit der Unicode-Bewusstsein in ES2015 gibt es plötzlich viel mehr Zeichen, die als Zahlen betrachtet werden könnten, z. B. die eingekreiste Ziffer Eins: 1 oder Wortzeichen, z. B. das chinesische Zeichen für Schnee: 雪.

Keine dieser Angaben kann \d oder \w zugeordnet werden. Eine Änderung der Bedeutung dieser Kurzschreibweisen würde bestehende Muster für reguläre Ausdrücke zerstören.

Stattdessen werden neue Escapesequenzen für Attribute eingeführt. Beachten Sie, dass sie nur für Unicode-fähige reguläre Ausdrücke verfügbar sind, die durch das Flag /u gekennzeichnet sind.

/\p{Number}/u.test('①');      // true
/\p{Alphabetic}/u.test('雪');  // true

Umgekehrt kann mit \P abgeglichen werden.

/\P{Number}/u.test('①');      // false
/\P{Alphabetic}/u.test('雪');  // false

Das Unicode-Konsortium definiert viele weitere Eigenschaften, z. B. für mathematische Symbole oder japanische Hiragana-Zeichen:

/^\p{Math}+$/u.test('∛∞∉');                            // true
/^\p{Script_Extensions=Hiragana}+$/u.test('ひらがな');  // true

Die vollständige Liste der unterstützten Unicode-Attributklassen finden Sie im aktuellen Spezifikationsvorschlag. Weitere Beispiele findest du in diesem informativen Artikel.

Look-Behind-Assertions

Lookahead-Assertions waren von Anfang an Teil der JavaScript-Syntax für reguläre Ausdrücke. Ihr Gegenstück, die LookBehind-Assertions, werden endlich eingeführt. Einige von Ihnen erinnern sich vielleicht, dass dies schon seit einiger Zeit Teil von V8 ist. Wir verwenden sogar LookBehind-Assertions im Hintergrund, um das in ES2015 angegebene Unicode-Flag zu implementieren.

Der Name beschreibt seine Bedeutung bereits ziemlich gut. Sie bietet eine Möglichkeit, ein Muster auf eine Übereinstimmung zu beschränken, wenn ihm das Muster in der Lookbehind-Gruppe vorangestellt ist. Es gibt sowohl passende als auch nicht übereinstimmende Geschmacksrichtungen:

/(?<=\$)\d+/.exec('$1 is worth about ¥123');  // ['1']
/(?<!\$)\d+/.exec('$1 is worth about ¥123');  // ['123']

Weitere Informationen finden Sie in unserem vorherigen Blogpost, in dem es um Assertions und Beispiele in zugehörigen V8-Testläufen geht.

Danksagungen

In diesem Blogpost wären einige der Personen, die hart daran gearbeitet haben, nicht vollständig zu erwähnen, insbesondere die Sprachexpertinnen Mathias Bynens, Dan Ehrenberg, Claude Pache, Brian Terlson, Thomas Wood, Gorkem Yakin und Irregexp Guru Erik Corry, der die Spezifikation von V.Erik Corry unterstützt; aber auch alle anderen.

Wir hoffen, Sie finden diese neuen Funktionen für reguläre Ausdrücke genauso begeistert wie wir.