2013-07-28 12 views
6

Cercavo questa partitaPerché String.match() non produce risultati attesi quando è presente un flag globale?

'/links/51f5382e7b7993e335000015'.match(/^\/links\/([0-9a-f]{24})$/g) 

e ottenuto:

['/links/51f5382e7b7993e335000015'] 

mentre mi aspettavo:

['/links/51f5382e7b7993e335000015', '51f5382e7b7993e335000015'] 

ho avuto fortuna fino a quando ho rimosso il flag globale, che ho fatto Non pensare che possa influire sui risultati dei miei risultati!

Con il flag globale rimosso,

'/links/51f5382e7b7993e335000015'.match(/^\/links\/([0-9a-f]{24})$/) 

prodotto:

[ '/links/51f5382e7b7993e335000015', 
    '51f5382e7b7993e335000015', 
    index: 0, 
    input: '/links/51f5382e7b7993e335000015' ] 

che è fresco, ma leggendo la documentazione che non riesco a capire:

  • Perché la prima modulo non ha funzionato
  • Perché la bandiera globale ha interferito con lo () corrispondenti
  • Come ottenere il mio risultato previsto senza le index e input proprietà

On JavaScript Regex and Submatches la risposta in alto dice:

Uso partita di String() la funzione non restituirà catturato gruppi se la il modificatore globale è impostato, come hai scoperto.

Tuttavia,

> 'fofoofooofoooo'.match(/f(o+)/g) 
["fo", "foo", "fooo", "foooo"] 

sembra produrre gruppi catturati bene.

Grazie.

+0

Ho modificato la domanda per risolvere il possibile problema duplicato. –

+1

È un duplicato, ma +1 per "Ho provato ..., ho ottenuto ..., mi aspettavo ...". Vorrei che più domande fossero così. – FakeRainBrigand

+0

Hah! Grazie ... guarderò di nuovo, e più attentamente, alla pagina collegata. –

risposta

3

Da this msdn documentation per metodo match:

Se il flag globale (g) non è impostato, Elemento zero della matrice contiene l'intera partita, mentre gli elementi da 1 a n contengono submatches. Questo comportamento è uguale al comportamento del metodo exec (espressione regolare) (JavaScript) quando non è impostato il flag globale. Se è impostato il flag globale, gli elementi da 0 a n contengono tutte le corrispondenze che si sono verificate.

Enfasi mia.

Così, nel vostro 1 ° caso:

'/links/51f5382e7b7993e335000015'.match(/^\/links\/([0-9a-f]{24})$/g) 

Dal /g modificatore è impostato, verrà restituito solo le partite complete che si sono verificati, e non i submatches. Questo è il motivo per cui hai appena ottenuto un array con un singolo elemento. Poiché esiste solo una corrispondenza per quella regex.

2 ° caso:

'/links/51f5382e7b7993e335000015'.match(/^\/links\/([0-9a-f]{24})$/) 

/g modificatore non è impostato. Quindi la matrice contiene la corrispondenza completa all'indice 0th. E ulteriori elementi (1 ° indice) in array sono submatches - in questo caso, 1 ° gruppo di cattura.


Per quanto riguarda la tua ultima esempio:

'fofoofooofoooo'.match(/f(o+)/g) 

Anche in questo caso, dal momento che /g modificatore è impostato, verrà restituito tutte le partite dalla stringa, e non i submatches. Così, nella stringa, la regex f(o+) corrisponde 4 volte:

fo - 1st complete match (sub-match 'o' in 1st captured group ignored) 
foo - 2nd complete match (sub-match 'oo' ignored) 
fooo - 3rd complete match (sub-match 'ooo' ignored) 
foooo - 4th complete match (sub-match 'oooo' ignored) 

Se si utilizza l'ultima espressione regolare, senza /g modificatore, si otterrebbe ogni submatch come elemento separato, per la prima partita. Prova:

'fofoofooofoooo'.match(/f(o+)/) 

otterrete:

["fo", "o"] // With index and input element of course. 

Senza /g semplicemente ferma dopo la prima partita (fo), e restituisce l'intera partita e sub-partite.

+0

Grazie mille per questo Rohit! Wow, apprezzo davvero questa risposta. –

+0

@dimadima Prego :) –

+0

Rohit: In realtà, ''fofoofooofoooo.match (/ f (o +) /)' produce '[' fo ',' o ', indice: 0, input:' fofoofooofoooo '] '. Credo che questo sia dovuto al fatto che non ci sono backtracking. –

1

Secondo MDN, se il flag g non è specificato, restituisce gli stessi risultati di RegExp.exec(), che restituisce un array che include elementi per l'acquisizione di parentesi.

Se viene specificato il flag g, viene restituito un array contenente tutte le corrispondenze.

Questa descrizione è coerente con gli esempi nella questione, ma i vostri due esempi sono una sorta di mele con le arance:

  • tua espressione regolare "link" corrisponde l'intera stringa di input, una volta, possibilmente con un gruppo catturato a seconda sulla bandiera
  • L'espressione regolare /f(o+)/g corrisponde a diverse sottostringhe nell'input.
+0

Grazie per questa risposta e per il chiarimento del mio esempio –

Problemi correlati