Perché regex.exec () di Javascript non restituisce sempre lo stesso valore?

Nella console di Chrome o Firebug:

reg = /ab/g str = "abc" reg.exec(str) ==> ["ab"] reg.exec(str) ==> null reg.exec(str) ==> ["ab"] reg.exec(str) ==> null 

Exec è in qualche modo stato e dipende da cosa è stato restituito la volta precedente? O è solo un insetto? Non riesco a farlo accadere tutto il tempo. Ad esempio, se “str” ​​sopra erano “abc abc” non succede.

Un object RegExp JavaScript ha lo stato.

Quando la regex è globale, se chiami un metodo lo stesso object regex, inizierà dall’indice oltre la fine dell’ultima corrispondenza.

Quando non vengono trovate altre corrispondenze, l’indice viene reimpostato su 0 automaticamente.


Per ripristinarlo manualmente, imposta la proprietà lastIndex .

 reg.lastIndex = 0; 

Questa può essere una caratteristica molto utile. È ansible iniziare la valutazione in qualsiasi punto della stringa, se lo si desidera, o se in un ciclo, è ansible arrestarlo dopo un numero desiderato di corrispondenze.


Ecco una dimostrazione di un approccio tipico all’utilizzo della regex in un ciclo. Si avvale del fatto che exec restituisce null quando non ci sono più corrispondenze eseguendo l’assegnazione come condizione del ciclo.

 var re = /foo_(\d+)/g, str = "text foo_123 more text foo_456 foo_789 end text", match, results = []; while (match = re.exec(str)) results.push(+match[1]); 

DEMO: http://jsfiddle.net/pPW8Y/


Se non ti piace il posizionamento del compito, il ciclo può essere rielaborato, come questo ad esempio …

 var re = /foo_(\d+)/g, str = "text foo_123 more text foo_456 foo_789 end text", match, results = []; do { match = re.exec(str); if (match) results.push(+match[1]); } while (match); 

DEMO: http://jsfiddle.net/pPW8Y/1/

Da documenti MDN :

Se la tua espressione regolare usa il flag “g”, puoi usare il metodo exec più volte per trovare corrispondenze successive nella stessa stringa. Quando si esegue questa operazione, la ricerca inizia dalla sottostringa di str specificata dalla proprietà lastIndex dell’espressione regolare (il test avanza anche la proprietà lastIndex).

Dal momento che stai usando il flag g , exec continua dall’ultima stringa con corrispondenza fino alla fine (restituisce null ), quindi ricomincia.


Personalmente, preferisco andare al contrario con str.match(reg)

Più partite

Se la tua lastIndex bisogno del flag g (global match), dovrai resettare l’indice (posizione dell’ultima corrispondenza) usando la proprietà lastIndex .

reg.lastIndex = 0;

Ciò è dovuto al fatto che exec() si fermerà ad ogni occorrenza in modo da poter eseguire nuovamente la parte rimanente . Questo comportamento esiste anche con test() ):

Se la tua espressione regolare usa il flag “g”, puoi usare il metodo exec più volte per trovare corrispondenze successive nella stessa stringa. Quando si esegue questa operazione, la ricerca inizia dalla sottostringa di str specificata dalla proprietà lastIndex dell’espressione regolare (il test avanza anche la proprietà lastIndex)

Partita singola

Quando esiste una sola corrispondenza ansible, puoi semplicemente riscrivere l’espressione regolare omettendo la flag g , poiché l’ indice verrà automaticamente reimpostato su 0 .