perché l'espressione regolare, quando si utilizza la ricerca globale e il quantificatore {0,}, corrisponde alla fine della stringa?

4

Ho posto una domanda qui su js, regex, quantificatori e ricerca globale. Ho finalmente capito come funziona, ma, facciamo un esempio concreto e poi scriverò la mia domanda.

Basato sullo stesso esempio

var str = 'ddd';
var r = /d*/g;
console.log(str.match(r))

emette questo array: ["ddd", ""]

Capisco che il primo elemento nell'array sia perché corrisponde alla lettera d e l'ultimo elemento (quella stringa vuota) è perché corrisponde alla fine della stringa, che non è nulla, quindi * ha senso perché corrisponde a 0 o più occorrenze ...

Quindi, le mie domande sono:

  • Perché questo sta accadendo?
  • Perché basta interrogare la fine della stringa per ottenere finalmente a true matching?

Secondo me, la fine della stringa (ddd) non dovrebbe essere interrogata; perché non è come se la mia stringa contenesse uno spazio vuoto alla fine 'ddd'. Se la mia stringa era vuota, era logico corrispondere, ma non in questo caso. La mia logica qui è questa:

per ogni carattere nella stringa, fai questa ricerca / regex (d *) ... quindi perché continua semplicemente con la fine della stringa? Dovrebbe fermarsi sull'ultimo charachter della mia stringa, che in questo caso è d ...

    
posta Gigi Ionel 30.07.2015 - 11:05
fonte

2 risposte

4

match è solo un wrapper per exec , per ES5 15.5. 4.10, passaggio 8 (f) (i) :

Let result be the result of calling the [[Call]] internal method of exec with rx as the this value and argument list containing S.

Per un'espressione regolare globale, match chiama continuamente exec finché exec esegue di nuovo un valore null .

Quando guarda exec , vediamo che ognuno chiama a exec con un'espressione regolare globale aumenta lastIndex dell'oggetto regex dopo che la corrispondenza è stata effettuata:

  1. Let e be r's endIndex value.
  2. If global is true,
    • Call the [[Put]] internal method of R with arguments "lastIndex", e, and true.

Tuttavia ( ecco la vera risposta meccanica ), lastMatch viene ripristinato solo da exec quando è strettamente più grande della lunghezza della stringa:

  1. Let i be the value of ToInteger(lastIndex).

...

  1. If i < 0 or i > length, then
    • Call the [[Put]] internal method of R with arguments "lastIndex", 0, and true.
    • Return null.

(nota i > length , non i >= length .)

Pertanto, ci sarà un ultimo tentativo di abbinare la sottostringa il cui limite sinistro è lastIndex e il cui limite destro è la fine della stringa. Poiché la corrispondenza finale viene eseguita quando tali posizioni sono identiche, viene sempre eseguito un ultimo tentativo di corrispondenza sulla stringa vuota.

Come succede, d* corrisponde alla stringa vuota (poiché * corrisponde a zero e superiori), in modo che la corrispondenza sia inclusa nei risultati di match .

Non posso offrire una spiegazione infallibile perché la corrispondenza non si ferma quando lastIndex è uguale alla lunghezza della stringa. La mia ipotesi è che questo controllo finale a stringa vuota sia necessario per abbinare regex a terminale di lunghezza zero come /$/ che non corrisponderebbe mai se considerato su una sottostringa di lunghezza diversa da zero.

    
risposta data 30.07.2015 - 22:43
fonte
2

La tua espressione regolare corrisponde alla stringa '' vuota con d* , perché il quantificatore * indica zero o molte volte e qui è pari a zero% did.

Ed è abbinato perché quando usi il modificatore g non si fermerà nella prima partita e continuerà a corrispondere, ecco perché otterrai la seconda corrispondenza.

Questa è una DEMO senza il modificatore g e non corrisponde il '' .

Quindi, se non vuoi che corrisponda al secondo, puoi semplicemente rimuovere il modificatore g o meglio usare una delle espressioni regolari seguenti:

var r = /(^d*$)/g;
//Or the following one
var r = /(d+)/g;

Lo imporrà per ottenere solo le stringhe che contengono esattamente la lettera d .

Puoi vedere DEMO qui.

    
risposta data 30.07.2015 - 11:13
fonte