meci Vs exec în JavaScript [duplicat] (Programare, Javascript, Regex)

user3399784 a intrebat.

Am nevoie de unele clarificări pentru meci Vs exec în JavaScript; aici cineva spune că

„exec cu o expresie regulată globală este menit să fie folosit într-o buclă” dar în primul rând după cum vedeți în exemplul meu nu este cazul; în exemplul meu exec cu expresie regulată globală returnează toate meciurile într-un array! În al doilea rând, se spune că String.match returnează toate corespondențele fără a fi nevoie de o buclă! Dar, din nou, acest lucru nu se întâmplă în exemplul meu și se returnează doar șirul de intrare? Am înțeles greșit sau am făcut ceva greșit?

var myString = "[22].[44].[33].";
var myRegexp = /.*[(d*)*].*[(d*)*].*[(d*)*].*/g;

var execResult = myRegexp.exec(myString);
console.log(execResult.length);
console.log(execResult[1]);// returns 22 and execResult has all of my matches from index 1 to the length of array


var matchResult = myString.match(myRegexp);
console.log(matchResult.length);
console.log(matchResult);// returns just myString which is "[22].[44].[33]."! Why is that?

2 răspunsuri
thefourtheye
  1. string.match găsește prima potrivire și o returnează cu potrivirea efectivă, indexul la care a fost găsit textul și intrarea efectivă, atunci când nu se folosește indicatorul global.

  2. string.match returnează doar toate potrivirile, atunci când se utilizează indicatorul global.

Principala diferență între string.match și regex.exec este că regex va fi actualizat în ceea ce privește meciul curent cu regex.exec apel. De exemplu,

va returna

[ '22', index: 1, input: '[22].[44].[33].' ] 3
[ '44', index: 6, input: '[22].[44].[33].' ] 8
[ '33', index: 11, input: '[22].[44].[33].' ] 13

După cum se poate observa, funcția lastIndex este actualizată ori de câte ori se găsește o potrivire. Așadar, țineți cont de două lucruri atunci când utilizați exec, sau veți intra într-o buclă infinită.

  1. Dacă nu utilizați g atunci veți obține întotdeauna prima potrivire, dacă există una, altfel null. Astfel, următoarea operație va intra într-o buclă infinită.

    var myString = "[22].[44].[33].", myRegexp = /d+/, result;
    
    while (result = myRegexp.exec(myString)) {
        console.log(result, myRegexp.lastIndex);
    }
    
  2. Nu uitați să folosiți același obiect de expresie regulată la apelurile ulterioare. Deoarece obiectul regex este actualizat de fiecare dată și, dacă treceți un nou obiect, programul va intra din nou într-o buclă infinită.

    var myString = "[22].[44].[33].", result;
    
    while (result = /d+/g.exec(myString)) {
        console.log(result);
    }
    

Redu

String.prototype.match() și RegExp.prototype.exec() sunt similare prin faptul că ambele găsesc mai multe ocurențe și le returnează într-o matrice. Cu toate acestea, metoda exec returnează un array cu informații mai detaliate. De exemplu, spre deosebire de match, aceasta poate găsi și mai multe apariții ale grupurilor de captură. Așadar, dacă aveți grupuri de capturi, exec este esențială. Un lucru de reținut atunci când lucrați cu exec: nu trebuie să apelați if dintr-o regexp literală. Atribuiți mai întâi regex-ul la o variabilă și folosiți-o pentru a apela metoda exec. Un alt lucru este că, în timp ce match ar aduce mai multe ocurențe într-o matrice de elemente dintr-o dată, cu exec trebuie să iterați pentru fiecare ocurență care urmează să fie capturată.

Invocarea lui match este destul de simplă. Deoarece este o metodă prototip de șir de caractere, trebuie doar să o înlănțuiți cu un șir de caractere și să furnizați un regexp ca argument pentru metoda match, de exemplu: „test”.match(/es/) O reprezentare literală a unui regex poate fi utilizată fără probleme.

Invocarea exec este mai complicată. Așa cum am menționat anterior, este mai bine ca regex-ul să fie atribuit la ceva anterior. Bine, să vedem un exemplu

După cum vedeți, rezultatul lui exec include și grupurile de captură. Modul în care am ales să completez te array este oarecum neortodox, dar nu-mi place să folosesc un array temporar doar în partea condițională a buclei while. Acest lucru mi se pare mult mai îngrijit. Singurul lucru este că ultimul null care oprește bucla while este introdus la sfârșitul fișierului te array. De aici rezultă următoarele te.length-- instrucțiuni.

Editare: Acum există și instrucțiunea String.prototype.matchAll() disponibilă în browserele moderne, ceea ce ne ușurează în mare parte povara utilizării exec pe umerii noștri. Puteți să vă uitați la un alt răspuns al meu pentru a vedea asta în acțiune.

Comentarii

  • Cred că este înșelător să spunem „Deci, dacă aveți grupuri de captură, exec este esențial”, deoarece .match() returnează în mod clar o matrice cu toate grupurile capturate specificate. Implicați acest lucru în prima dvs. frază și, evident, știți cum funcționează fiecare. Poate că vrei să spui ceva mai mult de genul: „dacă ai nevoie să aplici recursiv unul sau mai multe grupuri de captură, folosind indicatorul global și .exec() sunt esențiale”? –  > Por ballenf.
  • @Ben Fletcher Mulțumesc. Da, corect, mă refeream la cazul în care se obțineau grupurile de captură atunci când era activat steagul global. Cu toate acestea, acum avem String.prototype.matchAll() care returnează un obiect iterator care dezvăluie toate grupurile capturate atunci când sunt răspândite. Menționat ca editare în răspunsul de mai sus. –  > Por Redu.