Dieses Kapitel gibt einen Überblick über die JavaScript-API für reguläre Ausdrücke. Es wird davon ausgegangen, dass Sie ungefähr wissen, wie sie funktionieren. Wenn nicht, gibt es viele gute Tutorials im Web. Zwei Beispiele sind:
Die hier verwendeten Begriffe spiegeln die Grammatik der ECMAScript-Spezifikation eng wider. Ich weiche manchmal ab, um Dinge leichter verständlich zu machen.
Die Syntax für allgemeine Atome lautet wie folgt:
Alle folgenden Zeichen haben eine Sonderbedeutung:
\ ^ $ . * + ? ( ) [ ] { } |Sie können sie durch Voranstellen eines Backslash maskieren. Zum Beispiel
> /^(ab)$/.test('(ab)')
false
> /^\(ab\)$/.test('(ab)')
trueZusätzliche Sonderzeichen sind
Innerhalb einer Zeichenklasse [...]
-
Innerhalb einer Gruppe, die mit einem Fragezeichen beginnt (?...)
: = ! < >
Die spitzen Klammern werden nur von der XRegExp-Bibliothek verwendet (siehe Kapitel 30), um Gruppen zu benennen.
. (Punkt)Passt zu jedem JavaScript-Zeichen (UTF-16-Codeeinheit) außer Zeilenumbrüchen (Neue Zeile, Wagenrücklauf usw.). Um wirklich jedes Zeichen abzugleichen, verwenden Sie [\s\S]. Zum Beispiel
> /./.test('\n')
false
> /[\s\S]/.test('\n')
true\f (Seitenvorschub), \n (Zeilenvorschub, neue Zeile), \r (Wagenrücklauf), \t (horizontaler Tabulator) und \v (vertikaler Tabulator).\0 passt zum NUL-Zeichen (\u0000).\cA – \cZ.\u0000 – \xFFFF (Unicode-Codeeinheiten; siehe Kapitel 24).\x00 – \xFF.\d passt zu jeder Ziffer (gleichbedeutend mit [0-9]); \D passt zu jeder Nicht-Ziffer (gleichbedeutend mit [^0-9]).\w passt zu jedem lateinischen alphanumerischen Zeichen plus Unterstrich (gleichbedeutend mit [A-Za-z0-9_]); \W passt zu allen Zeichen, die nicht von \w abgeglichen werden.\s passt zu Leerzeichen (Leerzeichen, Tabulator, Zeilenvorschub, Wagenrücklauf, Seitenvorschub, alle Unicode-Leerzeichen usw.); \S passt zu allen Nicht-Leerzeichen.Die Syntax für Zeichenklassen lautet wie folgt:
[«charSpecs»] passt zu jedem einzelnen Zeichen, das mindestens einer der charSpecs entspricht.[^«charSpecs»] passt zu jedem einzelnen Zeichen, das keiner der charSpecs entspricht.Die folgenden Konstrukte sind alle Zeichen spezifikationen
Quellzeichen passen zu sich selbst. Die meisten Zeichen sind Quellzeichen (sogar viele Zeichen, die anderswo besonders sind). Nur drei Zeichen sind es nicht
\ ] -
Wie üblich maskieren Sie mit einem Backslash. Wenn Sie einen Bindestrich maskieren möchten, ohne ihn zu maskieren, muss er das erste Zeichen nach der öffnenden Klammer oder die rechte Seite eines Bereichs sein, wie kurz beschrieben.
Klassescapes: Jede der zuvor aufgeführten Zeichenescapes und Zeichenklassescapes ist zulässig. Es gibt eine zusätzliche Escape
\b): Außerhalb einer Zeichenklasse passt \b zu Wortgrenzen. Innerhalb einer Zeichenklasse passt es zum Steuerzeichen *Backspace*.-), gefolgt von einem Quellzeichen oder einem Klassenscape.Um die Verwendung von Zeichenklassen zu demonstrieren, analysiert dieses Beispiel ein Datum im ISO 8601-Format
functionparseIsoDate(str){varmatch=/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.exec(str);// Other ways of writing the regular expression:// /^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$/// /^(\d\d\d\d)-(\d\d)-(\d\d)$/if(!match){thrownewError('Not an ISO date: '+str);}console.log('Year: '+match[1]);console.log('Month: '+match[2]);console.log('Day: '+match[3]);}
Und hier ist die Interaktion
> parseIsoDate('2001-12-24')
Year: 2001
Month: 12
Day: 24Die Syntax für Gruppen lautet wie folgt:
(«pattern») ist eine erfassende Gruppe. Was auch immer von pattern abgeglichen wird, kann über Rückverweise oder als Ergebnis einer Abgleichoperation abgerufen werden.(?:«pattern») ist eine nicht erfassende Gruppe. pattern wird immer noch gegen die Eingabe abgeglichen, aber nicht als Erfassung gespeichert. Daher hat die Gruppe keine Nummer, auf die Sie (z. B. über einen Rückverweis) verweisen können.\1, \2 und so weiter werden als *Rückverweise* bezeichnet; sie verweisen auf eine zuvor abgeglichene Gruppe. Die Zahl nach dem Backslash kann jede ganze Zahl größer oder gleich 1 sein, aber die erste Ziffer darf nicht 0 sein.
In diesem Beispiel garantiert ein Rückverweis die gleiche Menge an a's vor und nach dem Bindestrich
> /^(a+)-\1$/.test('a-a')
true
> /^(a+)-\1$/.test('aaa-aaa')
true
> /^(a+)-\1$/.test('aa-a')
falseDieses Beispiel verwendet einen Rückverweis, um ein HTML-Tag abzugleichen (offensichtlich sollten Sie normalerweise einen richtigen Parser zur Verarbeitung von HTML verwenden)
> var tagName = /<([^>]+)>[^<]*<\/\1>/;
> tagName.exec('<b>bold</b>')[1]
'b'
> tagName.exec('<strong>text</strong>')[1]
'strong'
> tagName.exec('<strong>text</stron>')
nullJedes Atom (einschließlich Zeichenklassen und Gruppen) kann von einem Quantifizierer gefolgt werden:
? bedeutet null oder einmal.* bedeutet null oder mehrfach.+ bedeutet einmal oder mehrfach.{n} bedeutet genau n Mal.{n,} bedeutet n oder mehr Mal.{n,m} bedeutet mindestens n, höchstens m Mal.Standardmäßig sind Quantifizierer *gierig*; das heißt, sie passen so viel wie möglich. Sie können *zurückhaltendes* Abgleichen (so wenig wie möglich) erhalten, indem Sie jeden der vorherigen Quantifizierer (einschließlich der Bereiche in geschweiften Klammern) mit einem Fragezeichen (?) versehen. Zum Beispiel:
> '<a> <strong>'.match(/^<(.*)>/)[1] // greedy 'a> <strong' > '<a> <strong>'.match(/^<(.*?)>/)[1] // reluctant 'a'
Daher ist .*? ein nützliches Muster, um alles bis zum nächsten Vorkommen des folgenden Atoms abzugleichen. Zum Beispiel ist das Folgende eine kompaktere Version des regulären Ausdrucks für HTML-Tags, der gerade gezeigt wurde (der [^<]* anstelle von .*? verwendete)
/<(.+?)>.*?<\/\1>/Assertionen, die in der folgenden Liste aufgeführt sind, sind Prüfungen der aktuellen Position in der Eingabe:
| Passt nur am Anfang der Eingabe. |
| Passt nur am Ende der Eingabe. |
| Passt nur an einer Wortgrenze. Nicht verwechseln mit |
| Passt nur, wenn nicht an einer Wortgrenze. |
| Positive Lookahead: Passt nur, wenn |
| Negative Lookahead: Passt nur, wenn |
Dieses Beispiel passt zu einer Wortgrenze mit \b
> /\bell\b/.test('hello')
false
> /\bell\b/.test('ello')
false
> /\bell\b/.test('ell')
trueDieses Beispiel passt zum Inneren eines Wortes mit \B
> /\Bell\B/.test('ell')
false
> /\Bell\B/.test('hell')
false
> /\Bell\B/.test('hello')
trueLookbehind wird nicht unterstützt. Manuelles Implementieren von Lookbehind erklärt, wie es manuell implementiert werden kann.
Ein Disjunktionsoperator (|) trennt zwei Alternativen; entweder die Alternativen müssen übereinstimmen, damit die Disjunktion übereinstimmt. Die Alternativen sind Atome (optional einschließlich Quantifizierern).
Der Operator bindet sehr schwach, sodass Sie vorsichtig sein müssen, dass die Alternativen nicht zu weit reichen. Zum Beispiel passt der folgende reguläre Ausdruck zu allen Zeichenketten, die entweder mit aa beginnen oder mit bb enden
> /^aa|bb$/.test('aaxx')
true
> /^aa|bb$/.test('xxbb')
trueMit anderen Worten, die Disjunktion bindet schwächer als sogar ^ und $, und die beiden Alternativen sind ^aa und bb$. Wenn Sie die beiden Zeichenketten 'aa' und 'bb' abgleichen möchten, benötigen Sie Klammern
/^(aa|bb)$/
Ebenso, wenn Sie die Zeichenketten 'aab' und 'abb' abgleichen möchten
/^a(a|b)b$/
JavaScript-Reguläre Ausdrücke haben nur sehr begrenzte Unterstützung für Unicode. Insbesondere wenn es um Code-Punkte in den Astralebenen geht, müssen Sie vorsichtig sein. Kapitel 24 erklärt die Details.
Sie können einen regulären Ausdruck entweder über ein Literal oder einen Konstruktor erstellen und konfigurieren, wie er über Flags funktioniert.
Es gibt zwei Möglichkeiten, einen regulären Ausdruck zu erstellen: Sie können ein Literal oder den Konstruktor RegExp verwenden:
Literal |
| Kompiliert beim Laden |
Konstruktor (zweites Argument ist optional) |
| Kompiliert zur Laufzeit |
Ein Literal und ein Konstruktor unterscheiden sich darin, wann sie kompiliert werden
Das Literal wird beim Laden kompiliert. Der folgende Code löst eine Ausnahme aus, wenn er ausgewertet wird
functionfoo(){/[/;}
Der Konstruktor kompiliert den regulären Ausdruck, wenn er aufgerufen wird. Der folgende Code löst keine Ausnahme aus, aber das Aufrufen von foo() wird dies tun:
functionfoo(){newRegExp('[');}
Daher sollten Sie normalerweise Literale verwenden, aber Sie benötigen den Konstruktor, wenn Sie einen regulären Ausdruck dynamisch zusammensetzen möchten.
Flags sind ein Suffix von regulären Ausdrucksliteralen und ein Parameter von regulären Ausdruckskonstruktoren; sie modifizieren das Abgleichverhalten von regulären Ausdrücken. Es gibt die folgenden Flags:
| Kurzname | Langname | Beschreibung |
|
| Der angegebene reguläre Ausdruck wird mehrmals abgeglichen. Beeinflusst mehrere Methoden, insbesondere |
|
| Groß-/Kleinschreibung wird beim Abgleichen des angegebenen regulären Ausdrucks ignoriert. |
|
| Im Multiline-Modus passen der Anfangsoperator |
Der Kurzname wird für Literalpräfixe und Konstruktorparameter verwendet (siehe Beispiele im nächsten Abschnitt). Der Langname wird für Eigenschaften eines regulären Ausdrucks verwendet, die angeben, welche Flags während seiner Erstellung gesetzt wurden.
Reguläre Ausdrücke haben die folgenden Instanzeigenschaften:
Flags: boolesche Werte, die angeben, welche Flags gesetzt sind
global: Ist das Flag /g gesetzt?ignoreCase: Ist das Flag /i gesetzt?multiline: Ist das Flag /m gesetzt?Daten für mehrfache Übereinstimmungen (Flag /g ist gesetzt)
lastIndex ist der Index, an dem die Suche fortgesetzt wird.Das Folgende ist ein Beispiel für den Zugriff auf die Instanzeigenschaften für Flags
> var regex = /abc/i; > regex.ignoreCase true > regex.multiline false
In diesem Beispiel erstellen wir denselben regulären Ausdruck zuerst mit einem Literal und dann mit einem Konstruktor und verwenden die test()-Methode, um festzustellen, ob er mit einer Zeichenkette übereinstimmt:
> /abc/.test('ABC')
false
> new RegExp('abc').test('ABC')
falseIn diesem Beispiel erstellen wir einen regulären Ausdruck, der die Groß-/Kleinschreibung ignoriert (Flag /i)
> /abc/i.test('ABC')
true
> new RegExp('abc', 'i').test('ABC')
trueDie test()-Methode prüft, ob ein regulärer Ausdruck regex mit einer Zeichenkette str übereinstimmt:
regex.test(str)
test() verhält sich je nachdem, ob das Flag /g gesetzt ist oder nicht, unterschiedlich.
Wenn das Flag /g nicht gesetzt ist, prüft die Methode, ob irgendwo in str eine Übereinstimmung besteht. Zum Beispiel
> var str = '_x_x'; > /x/.test(str) true > /a/.test(str) false
Wenn das Flag /g gesetzt ist, gibt die Methode true so oft zurück, wie es Übereinstimmungen für regex in str gibt. Die Eigenschaft regex.lastIndex enthält den Index nach der letzten Übereinstimmung
> var regex = /x/g; > regex.lastIndex 0 > regex.test(str) true > regex.lastIndex 2 > regex.test(str) true > regex.lastIndex 4 > regex.test(str) false
Die search()-Methode sucht nach einer Übereinstimmung mit regex innerhalb von str:
str.search(regex)
Wenn eine Übereinstimmung besteht, wird der Index, an dem sie gefunden wurde, zurückgegeben. Andernfalls ist das Ergebnis -1. Die Eigenschaften global und lastIndex von regex werden ignoriert, da die Suche durchgeführt wird (und lastIndex nicht geändert wird).
Zum Beispiel
> 'abba'.search(/b/) 1 > 'abba'.search(/x/) -1
Wenn das Argument von search() kein regulärer Ausdruck ist, wird es in einen solchen umgewandelt
> 'aaab'.search('^a+b+$')
0Der folgende Methodenaufruf erfasst Gruppen während des Abgleichs von regex mit str:
varmatchData=regex.exec(str);
Wenn keine Übereinstimmung vorhanden war, ist matchData null. Andernfalls ist matchData ein *Ergebnis der Übereinstimmung*, ein Array mit zwei zusätzlichen Eigenschaften
input ist die vollständige Eingabezeichenkette.index ist der Index, an dem die Übereinstimmung gefunden wurde.Wenn das Flag /g nicht gesetzt ist, wird nur die erste Übereinstimmung zurückgegeben
> var regex = /a(b+)/;
> regex.exec('_abbb_ab_')
[ 'abbb',
'bbb',
index: 1,
input: '_abbb_ab_' ]
> regex.lastIndex
0Wenn das Flag /g gesetzt ist, werden alle Übereinstimmungen zurückgegeben, wenn Sie exec() wiederholt aufrufen. Der Rückgabewert null signalisiert, dass keine weiteren Übereinstimmungen vorhanden sind. Die Eigenschaft lastIndex gibt an, wo die Übereinstimmung das nächste Mal fortgesetzt wird
> var regex = /a(b+)/g; > var str = '_abbb_ab_'; > regex.exec(str) [ 'abbb', 'bbb', index: 1, input: '_abbb_ab_' ] > regex.lastIndex 6 > regex.exec(str) [ 'ab', 'b', index: 7, input: '_abbb_ab_' ] > regex.lastIndex 10 > regex.exec(str) null
Hier schleifen wir über Übereinstimmungen
varregex=/a(b+)/g;varstr='_abbb_ab_';varmatch;while(match=regex.exec(str)){console.log(match[1]);}
und wir erhalten die folgende Ausgabe
bbb b
Der folgende Methodenaufruf gleicht regex mit str ab:
varmatchData=str.match(regex);
Wenn das Flag /g von regex nicht gesetzt ist, verhält sich diese Methode wie RegExp.prototype.exec()
> 'abba'.match(/a/) [ 'a', index: 0, input: 'abba' ]
Wenn das Flag gesetzt ist, gibt die Methode ein Array mit allen übereinstimmenden Teilzeichenketten in str zurück (d. h. Gruppe 0 jeder Übereinstimmung) oder null, wenn keine Übereinstimmung vorhanden ist
> 'abba'.match(/a/g) [ 'a', 'a' ] > 'abba'.match(/x/g) null
Die replace()-Methode durchsucht eine Zeichenkette str nach Übereinstimmungen mit search und ersetzt sie durch replacement:
str.replace(search,replacement)
Es gibt mehrere Möglichkeiten, wie die beiden Parameter angegeben werden können
search
Entweder eine Zeichenkette oder ein regulärer Ausdruck
/g-Flag verwenden. Dies ist unerwartet und eine große Fallgrube.global-Flag, da sonst nur ein Versuch unternommen wird, den regulären Ausdruck abzugleichen.replacement
Entweder eine Zeichenkette oder eine Funktion
Wenn replacement eine Zeichenkette ist, wird ihr Inhalt wörtlich zum Ersetzen des Treffers verwendet. Die einzige Ausnahme ist das Sonderzeichen Dollarzeichen ($), das sogenannte *Ersetzungsdirektiven* einleitet:
$n fügt Gruppe n aus dem Treffer ein. n muss mindestens 1 sein ($0 hat keine besondere Bedeutung).Der übereinstimmende Teilzeichenkette
$` (Backtick) fügt den Text vor dem Treffer ein.$& fügt den vollständigen Treffer ein.$' (Apostroph) fügt den Text nach dem Treffer ein.$$ fügt ein einzelnes $ ein.Dieses Beispiel bezieht sich auf die übereinstimmende Teilzeichenkette und ihren Präfix und Suffix
> 'axb cxd'.replace(/x/g, "[$`,$&,$']") 'a[a,x,b cxd]b c[axb c,x,d]d'
Dieses Beispiel bezieht sich auf eine Gruppe
> '"foo" and "bar"'.replace(/"(.*?)"/g, '#$1#') '#foo# and #bar#'
Wenn replacement eine Funktion ist, berechnet sie die Zeichenkette, die den Treffer ersetzen soll. Diese Funktion hat die folgende Signatur:
function(completeMatch,group_1,...,group_n,offset,inputStr)
completeMatch ist dasselbe wie $& zuvor, offset gibt an, wo der Treffer gefunden wurde, und inputStr ist das, womit abgeglichen wird. Daher können Sie die spezielle Variable arguments verwenden, um Gruppen abzurufen (Gruppe 1 über arguments[1] und so weiter). Zum Beispiel
> function replaceFunc(match) { return 2 * match }
> '3 apples and 5 oranges'.replace(/[0-9]+/g, replaceFunc)
'6 apples and 10 oranges'Reguläre Ausdrücke, deren /g-Flag gesetzt ist, sind problematisch, wenn eine auf ihnen aufgerufene Methode mehrmals aufgerufen werden muss, um alle Ergebnisse zurückzugeben. Das ist bei zwei Methoden der Fall:
RegExp.prototype.test()
RegExp.prototype.exec()
Dann missbraucht JavaScript den regulären Ausdruck als Iterator, als Zeiger in die Ergebnisfolge. Das verursacht Probleme
/g-Reguläre Ausdrücke können nicht inline seinZum Beispiel
// Don’t do that:varcount=0;while(/a/g.test('babaa'))count++;
Die vorherige Schleife ist unendlich, da für jede Schleifeniteration ein neuer regulärer Ausdruck erstellt wird, der die Iteration über die Ergebnisse neu startet. Daher muss der Code umgeschrieben werden
varcount=0;varregex=/a/g;while(regex.test('babaa'))count++;
Hier ist ein weiteres Beispiel
// Don’t do that:functionextractQuoted(str){varmatch;varresult=[];while((match=/"(.*?)"/g.exec(str))!=null){result.push(match[1]);}returnresult;}
Das Aufrufen der vorherigen Funktion führt erneut zu einer Endlosschleife. Die korrekte Version ist (warum lastIndex auf 0 gesetzt ist, wird kurz erklärt)
varQUOTE_REGEX=/"(.*?)"/g;functionextractQuoted(str){QUOTE_REGEX.lastIndex=0;varmatch;varresult=[];while((match=QUOTE_REGEX.exec(str))!=null){result.push(match[1]);}returnresult;}
Verwenden der Funktion
> extractQuoted('"hello", "world"')
[ 'hello', 'world' ]Es ist eine bewährte Methode, sowieso nicht inline zu sein (dann können Sie regulären Ausdrücken beschreibende Namen geben). Aber Sie müssen sich bewusst sein, dass Sie dies nicht tun können, nicht einmal bei schnellen Hacks.
/g-Reguläre Ausdrücke als Parametertest() und exec() mehrmals aufrufen möchte, muss vorsichtig mit einem ihm als Parameter übergebenen regulären Ausdruck sein. Sein Flag /g muss aktiv sein und, um sicher zu sein, sollte sein lastIndex auf null gesetzt werden (eine Erklärung wird im nächsten Beispiel gegeben)./g-Reguläre Ausdrücke (z. B. Konstanten)lastIndex-Eigenschaft auf null setzen, bevor Sie ihn als Iterator verwenden (eine Erklärung wird im nächsten Beispiel gegeben). Da die Iteration von lastIndex abhängt, kann ein solcher regulärer Ausdruck nicht in mehr als einer Iteration gleichzeitig verwendet werden.Das folgende Beispiel veranschaulicht Problem 2. Es ist eine naive Implementierung einer Funktion, die zählt, wie viele Übereinstimmungen es für den regulären Ausdruck regex in der Zeichenkette str gibt
// Naive implementationfunctioncountOccurrences(regex,str){varcount=0;while(regex.test(str))count++;returncount;}
Hier ist ein Beispiel für die Verwendung dieser Funktion
> countOccurrences(/x/g, '_x_x') 2
Das erste Problem ist, dass diese Funktion in eine Endlosschleife gerät, wenn das /g-Flag des regulären Ausdrucks nicht gesetzt ist. Zum Beispiel
countOccurrences(/x/,'_x_x')// never terminates
Das zweite Problem ist, dass die Funktion nicht korrekt funktioniert, wenn regex.lastIndex nicht 0 ist, da diese Eigenschaft angibt, wo die Suche beginnen soll. Zum Beispiel
> var regex = /x/g; > regex.lastIndex = 2; > countOccurrences(regex, '_x_x') 1
Die folgende Implementierung behebt die beiden Probleme
functioncountOccurrences(regex,str){if(!regex.global){thrownewError('Please set flag /g of regex');}varorigLastIndex=regex.lastIndex;// storeregex.lastIndex=0;varcount=0;while(regex.test(str))count++;regex.lastIndex=origLastIndex;// restorereturncount;}
Eine einfachere Alternative ist die Verwendung von match()
functioncountOccurrences(regex,str){if(!regex.global){thrownewError('Please set flag /g of regex');}return(str.match(regex)||[]).length;}
Es gibt eine mögliche Fallgrube: str.match() gibt null zurück, wenn das /g-Flag gesetzt ist und keine Übereinstimmungen gefunden werden. Wir vermeiden diese Fallgrube im obigen Code, indem wir [] verwenden, wenn das Ergebnis von match() nicht wahrheitsgemäß ist.
Dieser Abschnitt gibt einige Tipps und Tricks für die Arbeit mit regulären Ausdrücken in JavaScript.
Manchmal, wenn Sie manuell einen regulären Ausdruck zusammensetzen, möchten Sie eine gegebene Zeichenkette wörtlich verwenden. Das bedeutet, dass keines der Sonderzeichen (z. B. *, [) als solches interpretiert werden sollte - alle müssen maskiert werden. JavaScript hat keine integrierten Mittel für diese Art von Zitieren, aber Sie können Ihre eigene Funktion, quoteText, programmieren, die wie folgt funktioniert:
> console.log(quoteText('*All* (most?) aspects.'))
\*All\* \(most\?\) aspects\.Eine solche Funktion ist besonders nützlich, wenn Sie eine Suche und Ersetzung mit mehreren Vorkommen durchführen müssen. Dann muss der zu suchende Wert ein regulärer Ausdruck mit gesetztem global-Flag sein. Mit quoteText() können Sie beliebige Zeichenketten verwenden. Die Funktion sieht so aus
functionquoteText(text){returntext.replace(/[\\^$.*+?()[\]{}|=!<>:-]/g,'\\$&');}
Alle Sonderzeichen werden maskiert, da Sie möglicherweise mehrere Zeichen innerhalb von Klammern oder eckigen Klammern maskieren möchten.
Wenn Sie keine Assertionen wie ^ und $ verwenden, finden die meisten Methoden für reguläre Ausdrücke ein Muster überall. Zum Beispiel:
> /aa/.test('xaay')
true
> /^aa$/.test('xaay')
falseEs ist ein seltener Anwendungsfall, aber manchmal benötigen Sie einen regulären Ausdruck, der alles oder nichts abgleicht. Zum Beispiel kann eine Funktion einen Parameter mit einem regulären Ausdruck haben, der zum Filtern verwendet wird. Wenn dieser Parameter fehlt, geben Sie ihm einen Standardwert, einen regulären Ausdruck, der alles abgleicht.
Der leere reguläre Ausdruck passt zu allem. Wir können eine Instanz von RegExp basierend auf diesem regulären Ausdruck wie folgt erstellen
> new RegExp('').test('dfadsfdsa')
true
> new RegExp('').test('')
trueDer leere reguläre Ausdruck literal wäre jedoch //, was von JavaScript als Kommentar interpretiert wird. Daher ist das Folgende das Nächstliegende, das Sie über ein Literal erhalten können: /(?:)/ (leere nicht erfassende Gruppe). Die Gruppe passt zu allem, ohne etwas zu erfassen, was die Gruppe vom Einfluss auf das von exec() zurückgegebene Ergebnis fernhält. Sogar JavaScript selbst verwendet die vorherige Darstellung, wenn es einen leeren regulären Ausdruck anzeigt
> new RegExp('')
/(?:)/Der leere reguläre Ausdruck hat eine Umkehrung - den regulären Ausdruck, der nichts abgleicht
> var never = /.^/;
> never.test('abc')
false
> never.test('')
falseLookbehind ist eine Assertion. Ähnlich wie bei Lookahead wird ein Muster verwendet, um etwas über die aktuelle Position in der Eingabe zu prüfen, aber ansonsten ignoriert. Im Gegensatz zu Lookahead muss der Treffer des Musters *enden* an der aktuellen Position (nicht dort beginnen).
Die folgende Funktion ersetzt jedes Vorkommen der Zeichenkette 'NAME' durch den Wert des Parameters name, aber nur, wenn das Vorkommen nicht von einem Anführungszeichen preceded wird. Wir behandeln das Anführungszeichen, indem wir das Zeichen vor dem aktuellen Treffer "manuell" prüfen
functioninsertName(str,name){returnstr.replace(/NAME/g,function(completeMatch,offset){if(offset===0||(offset>0&&str[offset-1]!=='"')){returnname;}else{returncompleteMatch;}});}
> insertName('NAME "NAME"', 'Jane')
'Jane "NAME"'
> insertName('"NAME" NAME', 'Jane')
'"NAME" Jane'Eine Alternative ist, die Zeichen einzuschließen, die maskieren können, in den regulären Ausdruck. Dann müssen Sie der Zeichenkette, in der Sie suchen, vorübergehend ein Präfix hinzufügen; andernfalls verpassen Sie Treffer am Anfang dieser Zeichenkette
functioninsertName(str,name){vartmpPrefix=' ';str=tmpPrefix+str;str=str.replace(/([^"])NAME/g,function(completeMatch,prefix){returnprefix+name;});returnstr.slice(tmpPrefix.length);// remove tmpPrefix}
Atome (siehe Atome: Allgemein)
. (Punkt) gleicht alles außer Zeilenumbrüchen (z. B. neue Zeilen) ab. Verwenden Sie [\s\S], um wirklich alles abzugleichen.Zeichenklassescapes
\d passt zu Ziffern ([0-9]); \D passt zu Nicht-Ziffern ([^0-9]).\w passt zu lateinischen alphanumerischen Zeichen plus Unterstrich ([A-Za-z0-9_]); \W passt zu allen anderen Zeichen.\s passt zu allen Leerzeichen (Leerzeichen, Tabulator, Zeilenvorschub usw.); \S passt zu allen Nicht-Leerzeichen.Zeichenklasse (Zeichensatz): [...] und [^...]
[abc] (alle Zeichen außer \ ] - stimmen mit sich selbst überein)[\d\w][A-Za-z0-9]Gruppen
(...); Rückverweis: \1(?:...)Quantifizierer (siehe Quantifizierer)
Gierig
? * +
{n} {n,} {n,m}
? nach jedem der gierigen Quantifizierer.Assertionen (siehe Assertionen)
^ $\b \B(?=...) (Muster muss folgen, wird aber ansonsten ignoriert)(?!...) (Muster darf nicht folgen, wird aber ansonsten ignoriert)Disjunktion: |
Erstellen eines regulären Ausdrucks (siehe Erstellen eines regulären Ausdrucks)
/xyz/i (beim Laden kompiliert)new RegExp('xzy', 'i') (zur Laufzeit kompiliert)Flags (siehe Flags)
/g (beeinflusst mehrere Methoden für reguläre Ausdrücke)/i/m (^ und $ passen pro Zeile, im Gegensatz zur vollständigen Eingabe)Methoden
regex.test(str): Gibt es eine Übereinstimmung (siehe RegExp.prototype.test: Gibt es eine Übereinstimmung?)?
/g nicht gesetzt ist: Gibt es irgendwo eine Übereinstimmung?/g gesetzt ist: Gibt true so oft zurück, wie es Übereinstimmungen gibt.str.search(regex): An welchem Index gibt es eine Übereinstimmung (siehe String.prototype.search: An welchem Index gibt es eine Übereinstimmung?)?
regex.exec(str): Erfassende Gruppen (siehe Abschnitt RegExp.prototype.exec: Erfassende Gruppen)?
/g nicht gesetzt ist: Erfasst nur die Gruppen der ersten Übereinstimmung (einmal aufgerufen)/g gesetzt ist: Erfasst die Gruppen aller Übereinstimmungen (wiederholt aufgerufen; gibt null zurück, wenn keine weiteren Übereinstimmungen vorhanden sind)
str.match(regex): Erfassende Gruppen oder Rückgabe aller übereinstimmenden Teilzeichenketten (siehe String.prototype.match: Erfassende Gruppen oder Rückgabe aller übereinstimmenden Teilzeichenketten)
/g nicht gesetzt ist: Erfassende Gruppen/g gesetzt ist: Gibt alle übereinstimmenden Teilzeichenketten in einem Array zurück
str.replace(search, replacement): Suchen und Ersetzen (siehe String.prototype.replace: Suchen und Ersetzen)
search: Zeichenkette oder regulärer Ausdruck (verwenden Sie letzteren, setzen Sie /g!)replacement: String (mit $1, etc.) oder Funktion (arguments[1] ist Gruppe 1, etc.), die eine Zeichenkette zurückgibtTipps zur Verwendung des Flags /g finden Sie unter Probleme mit dem Flag /g.
Mathias Bynens (@mathias) und Juan Ignacio Dopazo (@juandopazo) empfahlen die Verwendung von match() und test() zum Zählen von Vorkommen, und Šime Vidas (@simevidas) warnte mich davor, vorsichtig mit match() zu sein, wenn es keine Treffer gibt. Die Fallstricke des globalen Flags, das zu Endlosschleifen führt, stammen aus einem Vortrag von Andrea Giammarchi (@webreflection). Claude Pache riet mir, in quoteText() mehr Zeichen zu escapen.