Sie können auf folgende Erfassungsgruppen zugreifen:
var myString = "something format_abc";
var myRegexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
var match = myRegexp.exec(myString);
console.log(match[1]); // abc
Und wenn es mehrere Übereinstimmungen gibt, können Sie diese durchlaufen:
var myString = "something format_abc";
var myRegexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
match = myRegexp.exec(myString);
while (match != null) {
// matched text: match[0]
// match start: match.index
// capturing group n: match[n]
console.log(match[0])
match = myRegexp.exec(myString);
}
Bearbeiten: 2019-09-10
Wie Sie sehen können, war die Art und Weise, mehrere Übereinstimmungen zu durchlaufen, nicht sehr intuitiv. Dies führte zum Vorschlag der String.prototype.matchAll
Methode. Diese neue Methode wird voraussichtlich in der ECMAScript 2020-Spezifikation enthalten sein . Es gibt uns eine saubere API und löst mehrere Probleme. Es wurde gestartet, um auf gängigen Browsern und JS-Engines wie Chrome 73+ / Node 12+ und Firefox 67+ zu landen .
Die Methode gibt einen Iterator zurück und wird wie folgt verwendet:
const string = "something format_abc";
const regexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
const matches = string.matchAll(regexp);
for (const match of matches) {
console.log(match);
console.log(match.index)
}
Da es einen Iterator zurückgibt, können wir sagen, dass er faul ist. Dies ist nützlich, wenn besonders viele Erfassungsgruppen oder sehr große Zeichenfolgen erfasst werden. Bei Bedarf kann das Ergebnis jedoch mithilfe der Spread-Syntax oder der folgenden Array.from
Methode einfach in ein Array umgewandelt werden :
function getFirstGroup(regexp, str) {
const array = [...str.matchAll(regexp)];
return array.map(m => m[1]);
}
// or:
function getFirstGroup(regexp, str) {
return Array.from(str.matchAll(regexp), m => m[1]);
}
Während dieser Vorschlag mehr Unterstützung findet, können Sie in der Zwischenzeit das offizielle Shim-Paket verwenden .
Auch die internen Abläufe der Methode sind einfach. Eine äquivalente Implementierung unter Verwendung einer Generatorfunktion wäre wie folgt:
function* matchAll(str, regexp) {
const flags = regexp.global ? regexp.flags : regexp.flags + "g";
const re = new RegExp(regexp, flags);
let match;
while (match = re.exec(str)) {
yield match;
}
}
Eine Kopie des ursprünglichen regulären Ausdrucks wird erstellt. Dies dient dazu, Nebenwirkungen aufgrund der Mutation der lastIndex
Eigenschaft beim Durchlaufen der Mehrfachübereinstimmungen zu vermeiden .
Außerdem müssen wir sicherstellen, dass der reguläre Ausdruck das globale Flag hat, um eine Endlosschleife zu vermeiden.
Ich bin auch froh zu sehen, dass auch diese StackOverflow-Frage in den Diskussionen des Vorschlags erwähnt wurde .
var match = myString.match(myRegexp); // alert(match[1])
?string = string.substring(match.index + match[0].length)
Hier ist eine Methode, mit der Sie die n- te Erfassungsgruppe für jedes Spiel ermitteln können:
quelle
Das
\b
ist nicht genau das Gleiche. (Es funktioniert weiter--format_foo/
, funktioniert aber nicht weiterformat_a_b
) Aber ich wollte eine Alternative zu Ihrem Ausdruck zeigen, die in Ordnung ist. Natürlich ist dermatch
Anruf das Wichtigste.quelle
format_a_b
habe vor 6 Jahren nachträglich "funktioniert nicht " hinzugefügt , und ich erinnere mich nicht, was ich dort gemeint habe ... :-) Ich nehme an, es bedeutete "funktioniert nichta
nur zum Erfassen ", dh. der erste alphabetische Teil danachformat_
.In Bezug auf die obigen Beispiele für Klammern mit mehreren Übereinstimmungen habe ich hier nach einer Antwort gesucht, nachdem ich nicht das bekommen hatte, was ich wollte:
Nachdem ich mir die leicht verschlungenen Funktionsaufrufe mit while und .push () oben angesehen hatte, wurde mir klar, dass das Problem stattdessen sehr elegant mit mystring.replace () gelöst werden kann (das Ersetzen ist NICHT der Punkt und wird noch nicht einmal durchgeführt Die integrierte rekursive Funktionsaufrufoption CLEAN für den zweiten Parameter lautet!):
Danach glaube ich nicht, dass ich .match () jemals wieder für kaum etwas verwenden werde.
quelle
Zu guter Letzt habe ich eine Codezeile gefunden, die für mich gut funktioniert hat (JS ES6):
Dies wird zurückkehren:
quelle
replace
Ansatz von Alexz, weil dieser weniger vorausschauend und eleganter für mehrere Ergebnisse ist. Gute Arbeit, Sebastien H.In dieser Antwort verwendete Terminologie:
someString.match(regexPattern)
./format_(.*?)/g
Wo(.*?)
wäre eine übereinstimmende Gruppe?) Diese befinden sich in übereinstimmenden Mustern .Beschreibung
Um Zugriff auf die übereinstimmenden Gruppen zu erhalten , benötigen Sie in jedem der übereinstimmenden Muster eine Funktion oder ähnliches, um die Übereinstimmung zu durchlaufen . Es gibt eine Reihe von Möglichkeiten, wie Sie dies tun können, wie viele der anderen Antworten zeigen. Die meisten anderen Antworten verwenden eine while-Schleife, um alle übereinstimmenden Muster zu durchlaufen , aber ich denke, wir alle kennen die potenziellen Gefahren bei diesem Ansatz. Es ist notwendig, mit einem
new RegExp()
statt nur dem Muster selbst abzugleichen, das nur in einem Kommentar erwähnt wurde. Dies liegt daran, dass sich die.exec()
Methode ähnlich wie eine Generatorfunktion verhält - sie stoppt jedes Mal , wenn eine Übereinstimmung vorliegt, behält jedoch ihre Funktion bei.lastIndex
, um beim nächsten.exec()
Aufruf fortzufahren .Codebeispiele
Unten sehen Sie ein Beispiel für eine Funktion,
searchString
die einesArray
aller übereinstimmenden Muster zurückgibt , wobei jedesmatch
einArray
mit allen enthaltenen übereinstimmenden Gruppen ist . Anstatt eine while-Schleife zu verwenden, habe ich Beispiele bereitgestellt, die sowohl dieArray.prototype.map()
Funktion als auch eine performantere Methode verwenden - mithilfe einer einfachenfor
Schleife.Prägnante Versionen (weniger Code, mehr syntaktischer Zucker)
Diese sind weniger performant, da sie im Grunde eine
forEach
-schleife anstelle der schnellerenfor
-schleife implementieren.Performante Versionen (mehr Code, weniger syntaktischer Zucker)
Ich habe diese Alternativen noch nicht mit den zuvor in den anderen Antworten erwähnten verglichen, aber ich bezweifle, dass dieser Ansatz weniger leistungsfähig und weniger ausfallsicher ist als die anderen.
quelle
String#matchAll
(siehe Entwurf der Stufe 3 / Vorschlag vom 7. Dezember 2018 ) vereinfacht den Zugriff auf alle Gruppen im Übereinstimmungsobjekt (beachten Sie, dass Gruppe 0 die gesamte Übereinstimmung ist, während weitere Gruppen den Erfassungsgruppen im Muster entsprechen):Diese Methode liefert eine ähnliche Ausgabe wie
Regex.Matches
in C #,re.finditer
in Python,preg_match_all
in PHP.Sehen Sie sich eine JS-Demo an (getestet in Google Chrome 73.0.3683.67 (offizieller Build), Beta (64-Bit)):
Die
console.log([...matches])
ShowsSie können auch Übereinstimmungswerte oder bestimmte Gruppenwerte mit abrufen
HINWEIS : Siehe Details zur Browserkompatibilität .
quelle
Ihre Syntax ist wahrscheinlich nicht die beste. FF / Gecko definiert RegExp als Erweiterung der Funktion.
(FF2 ging so weit wie
typeof(/pattern/) == 'function'
)Es scheint, dass dies spezifisch für FF ist - IE, Opera und Chrome werfen alle Ausnahmen dafür aus.
Verwenden Sie stattdessen eine der zuvor von anderen genannten Methoden:
RegExp#exec
oderString#match
.Sie bieten die gleichen Ergebnisse:
quelle
Die
exec
Methode muss nicht aufgerufen werden! Sie können die "match" -Methode direkt für die Zeichenfolge verwenden. Vergiss nur nicht die Klammern.Position 0 hat eine Zeichenfolge mit allen Ergebnissen. Bei Position 1 wird die erste Übereinstimmung durch Klammern dargestellt, und bei Position 2 wird die zweite Übereinstimmung in Ihren Klammern isoliert. Verschachtelte Klammern sind schwierig, also Vorsicht!
quelle
Ein Einzeiler, der nur dann praktisch ist, wenn Sie ein einzelnes Klammerpaar haben:
quelle
while (match = myRegex.exec(myStr)) matches.push(match[1])
Verwenden Sie Ihren Code:
Bearbeiten: Safari 3, wenn es darauf ankommt.
quelle
Mit es2018 können Sie jetzt
String.match()
mit benannten Gruppen Ihren regulären Ausdruck deutlicher machen, was er versucht hat.und du wirst so etwas bekommen
quelle
quelle
Ihr Code funktioniert für mich (FF3 auf Mac), auch wenn ich PhiLo zustimme, dass der reguläre Ausdruck wahrscheinlich sein sollte:
(Aber natürlich bin ich mir nicht sicher, weil ich den Kontext der Regex nicht kenne.)
quelle
quelle
Es ist nicht wirklich eine explizite Schleife muß mehrere Übereinstimmungen analysieren - eine Ersatzfunktion als zweites Argument übergeben , wie beschrieben in :
String.prototype.replace(regex, func)
:Das
m0
Argument repräsentiert die volle angepaßte Teilzeichenfolge{0}
,{1}
usw.m1
stellt die erste Anpassungsgruppe, dh die in Klammern in den regex umschlossenen Teil , das ist0
für das erste Spiel. Undposition
ist der Startindex innerhalb der Zeichenfolge, in der die übereinstimmende Gruppe gefunden wurde - in diesem Fall nicht verwendet.quelle
In dem Code \ 1, der durch die erste Gruppe übereinstimmt ([az])
quelle
Einzeilige Lösung:
Sie können also folgendermaßen vorgehen (muss / g verwenden):
Ergebnis:
quelle
Holen Sie sich alle Gruppenvorkommen
quelle
Ich, du bist wie ich und wünschst, Regex würde ein Objekt wie dieses zurückgeben:
dann schnipsen Sie die Funktion von unten
quelle
BENUTZEN SIE NUR RegExp. $ 1 ... $ n-te Gruppe zB:
1.Um mit der 1. Gruppe RegExp. $ 1 übereinzustimmen
Wenn Sie 3 Gruppen in regulären Ausdrücken verwenden (beachten Sie die Verwendung nach string.match (reguläre Ausdrücke)).
RegExp. $ 1 RegExp. $ 2 RegExp. $ 3
quelle