riga - regular expression javascript example




Come si accede ai gruppi corrispondenti in un'espressione regolare JavaScript? (9)

Terminologia utilizzata in questa risposta:

  • La corrispondenza indica il risultato dell'esecuzione del pattern RegEx sulla stringa in questo modo: someString.match(regexPattern) .
  • I pattern abbinati indicano tutte le parti corrispondenti della stringa di input, che risiedono tutte all'interno della matrice di corrispondenza . 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. (Gli schemi tra parentesi, in questo modo: /format_(.*?)/g , dove (.*?) Sarebbe un gruppo con corrispondenza.) Questi si trovano all'interno di pattern abbinati .

Descrizione

Per ottenere l'accesso ai gruppi abbinati , in ciascuno degli schemi abbinati , è necessaria una funzione o qualcosa di simile a iterare sulla partita . Ci sono diversi modi in cui puoi farlo, come mostrano molte delle altre risposte. La maggior parte delle altre risposte usa un ciclo while per iterare su tutti i pattern abbinati , ma penso che tutti conosciamo i potenziali pericoli con questo approccio. È necessario confrontarsi con un new RegExp() anziché solo il pattern stesso, che è stato menzionato solo in un commento. Questo perché il metodo .exec() si comporta come una funzione di generatore : si ferma ogni volta che c'è una corrispondenza , ma mantiene il suo .lastIndex per continuare da lì alla successiva chiamata .exec() .

Esempi di codice

Di seguito è riportato un esempio di una funzione searchString che restituisce una Array di tutti i pattern con corrispondenza , in cui ogni match è una Array con tutti i gruppi corrispondenti contenenti. Invece di usare un ciclo while, ho fornito degli esempi usando sia la funzione Array.prototype.map() sia un modo più performante - usando un plain for -loop.

Versioni concise (meno codice, più zucchero sintattico)

Questi sono meno performanti dal momento che implementano fondamentalmente un forEach -loop invece del più veloce for -loop.

// 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 citate nelle altre risposte, ma dubito che questo approccio sia meno performante e meno sicuro degli altri.

Voglio abbinare una porzione di una stringa usando un'espressione regolare e quindi accedere alla sottostringa tra parentesi:

var myString = "something format_abc"; // I want "abc"

var arr = /(?:^|\s)format_(.*?)(?:\s|$)/.exec(myString);

console.log(arr);     // Prints: [" format_abc", "abc"] .. so far so good.
console.log(arr[1]);  // Prints: undefined  (???)
console.log(arr[0]);  // Prints: format_undefined (!!!)

Che cosa sto facendo di sbagliato?

Ho scoperto che non c'era nulla di sbagliato con il codice di espressione regolare sopra: la stringa vera contro la quale stavo testando era questa:

"date format_%A"

Segnalare che "% A" non è definito sembra un comportamento molto strano, ma non è direttamente correlato a questa domanda, quindi ne ho aperto uno nuovo, perché una sottostringa con corrispondenza restituisce "indefinito" in JavaScript? .

Il problema era che console.log suoi parametri come un'istruzione printf e dato che la stringa che stavo registrando ( "%A" ) aveva un valore speciale, cercava di trovare il valore del parametro successivo.


Ecco un metodo che puoi usare per ottenere il n ° gruppo di cattura per ogni partita:

function getMatches(string, regex, index) {
  index || (index = 1); // default to the first capturing group
  var matches = [];
  var match;
  while (match = regex.exec(string)) {
    matches.push(match[index]);
  }
  return matches;
}


// Example :
var myString = 'something format_abc something format_def something format_ghi';
var myRegEx = /(?:^|\s)format_(.*?)(?:\s|$)/g;

// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);

// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);


Non è necessario richiamare il metodo exec ! È possibile utilizzare il metodo "match" direttamente sulla stringa. Basta non dimenticare le parentesi.

var str = "This is cool";
var matches = str.match(/(This is)( cool)$/);
console.log( JSON.stringify(matches) ); // will print ["This is cool","This is"," cool"] or something like that...

La posizione 0 ha una stringa con tutti i risultati. La posizione 1 ha la prima corrispondenza rappresentata da parentesi e la posizione 2 ha la seconda corrispondenza isolata tra parentesi. Le parentesi annidate sono difficili, quindi attenzione!


Per quanto riguarda gli esempi di parentesi multi-match sopra, stavo cercando una risposta qui dopo non aver ottenuto ciò che volevo da:

var matches = mystring.match(/(?:neededToMatchButNotWantedInResult)(matchWanted)/igm);

Dopo aver osservato le chiamate di funzione un po 'contorte con while e .push () sopra, mi sono reso conto che il problema può essere risolto in modo molto elegante con mystring.replace () invece (la sostituzione NON è il punto, e non è nemmeno fatta , l'opzione di chiamata della funzione ricorsiva incorporata CLEAN per il secondo parametro è!):

var yourstring = 'something format_abc something format_def something format_ghi';

var matches = [];
yourstring.replace(/format_([^\s]+)/igm, function(m, p1){ matches.push(p1); } );

Dopo questo, non penso che userò mai .match () per quasi nulla mai più.


Puoi accedere ai gruppi di cattura come questo:

var myString = "something format_abc";
var myRegexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
var match = myRegexp.exec(myString);
console.log(match[1]); // abc

E se ci sono più fiammiferi puoi scorrere su di loro:

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);
}


Ultimo ma non meno importante, ho trovato che un codice di linea che ha funzionato bene per me (JS ES6):

var reg = /#([\S]+)/igm; //get hashtags
var string = 'mi alegría es total! ✌🙌\n#fiestasdefindeaño #PadreHijo #buenosmomentos #france #paris';

var matches = (string.match(reg) || []).map(e => e.replace(reg, '$1'));
console.log(matches);

questo ritornerà: [fiestasdefindeaño, PadreHijo, buenosmomentos, france, paris]


Usando il tuo codice:

console.log(arr[1]);  // prints: abc
console.log(arr[0]);  // prints:  format_abc

Modifica: Safari 3, se è importante.


function getMatches(string, regex, index) {
  index || (index = 1); // default to the first capturing group
  var matches = [];
  var match;
  while (match = regex.exec(string)) {
    matches.push(match[index]);
  }
  return matches;
}


// Example :
var myString = 'Rs.200 is Debited to A/c ...2031 on 02-12-14 20:05:49 (Clear Bal Rs.66248.77) AT ATM. TollFree 1800223344 18001024455 (6am-10pm)';
var myRegEx = /clear bal.+?(\d+\.?\d{2})/gi;

// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);

// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);

function getMatches(string, regex, index) {
  index || (index = 1); // default to the first capturing group
  var matches = [];
  var match;
  while (match = regex.exec(string)) {
    matches.push(match[index]);
  }
  return matches;
}


// Example :
var myString = 'something format_abc something format_def something format_ghi';
var myRegEx = /(?:^|\s)format_(.*?)(?:\s|$)/g;

// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);

// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);


/*Regex function for extracting object from "window.location.search" string.
 */

var search = "?a=3&b=4&c=7"; // Example search string

var getSearchObj = function (searchString) {

    var match, key, value, obj = {};
    var pattern = /(\w+)=(\w+)/g;
    var search = searchString.substr(1); // Remove '?'

    while (match = pattern.exec(search)) {
        obj[match[0].split('=')[0]] = match[0].split('=')[1];
    }

    return obj;

};

console.log(getSearchObj(search));






regex