Terminologia utilizzata in questa risposta:
- Partita indica il risultato di correre il vostro modello di RegEx contro la stringa in questo modo:
someString.match(regexPattern)
.
- I pattern corrispondenti indicano tutte le parti corrispondenti della stringa di input, che risiedono tutti all'interno della matrice di match . Queste sono tutte le istanze del tuo pattern all'interno della stringa di input.
- I gruppi corrispondenti indicano tutti i gruppi da catturare, definiti nel modello RegEx. (I motivi tra parentesi, in questo modo:,
/format_(.*?)/g
dove (.*?)
sarebbe un gruppo abbinato.) Questi risiedono all'interno di schemi abbinati .
Descrizione
Per ottenere l'accesso ai gruppi abbinati , in ciascuno dei modelli abbinati , è necessaria una funzione o qualcosa di simile per scorrere la corrispondenza . Ci sono molti modi per farlo, come mostrano molte altre risposte. La maggior parte delle altre risposte utilizza un ciclo while per scorrere tutti gli schemi corrispondenti , ma penso che tutti conosciamo i potenziali pericoli con questo approccio. È necessario abbinare contro un new RegExp()
invece che solo il modello stesso, che è stato menzionato solo in un commento. Questo perché il .exec()
metodo si comporta in modo simile a una funzione del generatore : si interrompe ogni volta che c'è una corrispondenza , ma continua .lastIndex
a continuare da lì alla .exec()
chiamata successiva .
Esempi di codice
Di seguito è riportato un esempio di una funzione searchString
che restituisce uno Array
di tutti i modelli corrispondenti , dove ognuno match
è un Array
con tutti i gruppi corrispondenti corrispondenti . Invece di usare un ciclo while, ho fornito esempi usando sia la Array.prototype.map()
funzione sia un modo più performante - usando un semplice for
ciclo.
Versioni concise (meno codice, più zucchero sintattico)
Questi sono meno performanti poiché fondamentalmente implementano un forEach
-loop anziché il for
-loop più veloce .
// Concise ES6/ES2015 syntax
const searchString =
(string, pattern) =>
string
.match(new RegExp(pattern.source, pattern.flags))
.map(match =>
new RegExp(pattern.source, pattern.flags)
.exec(match));
// Or if you will, with ES5 syntax
function searchString(string, pattern) {
return string
.match(new RegExp(pattern.source, pattern.flags))
.map(match =>
new RegExp(pattern.source, pattern.flags)
.exec(match));
}
let string = "something format_abc",
pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;
let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag
Versioni performanti (più codice, meno zucchero sintattico)
// Performant ES6/ES2015 syntax
const searchString = (string, pattern) => {
let result = [];
const matches = string.match(new RegExp(pattern.source, pattern.flags));
for (let i = 0; i < matches.length; i++) {
result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
}
return result;
};
// Same thing, but with ES5 syntax
function searchString(string, pattern) {
var result = [];
var matches = string.match(new RegExp(pattern.source, pattern.flags));
for (var i = 0; i < matches.length; i++) {
result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
}
return result;
}
let string = "something format_abc",
pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;
let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag
Devo ancora confrontare queste alternative con quelle precedentemente menzionate nelle altre risposte, ma dubito che questo approccio sia meno performante e meno sicuro degli altri.