Expresii regulate jquery exemple. Meciuri și grupe. Aplicarea unei expresii regulate unui șir

Expresiile regulate sau expresiile regulate sunt intimidante pentru începători, dar esențiale pentru orice programator. Să înțelegem expresiile regulate din 5 exemple simple cu JavaScript.

Dacă aveți o problemă și o veți rezolva cu expresii regulate, acum aveți două probleme. Există o zicală. Expresiile obișnuite găsite în cod provoacă uneori frică și ură la oamenii care nu sunt familiarizați cu ele.

Dar, de fapt, orice regex este doar o expresie șablon care poate rezolva problema unei întregi funcții într-o singură linie. Cu toate acestea, pentru a construi o expresie obișnuită, trebuie să țineți cont de un set de reguli stricte în care un începător se poate încurca și poate face greșeli.

Caractere potrivite

Cele mai elementare expresii regulate sunt cele care se potrivesc cu un singur caracter. Iată regulile lor:

1. Un punct (.) se potrivește cu orice caracter. Dacă trebuie să căutați un anumit punct, trebuie să scăpați de el folosind caracterul „\” (\.).

2. Un semn de întrebare (?) indică faptul că caracterul anterior este opțional. Pentru a căuta semnul de întrebare în sine într-un șir, acesta trebuie să fie și evadat cu „\” (\?).

var text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit lest. Donec convallis dignissim ligula, et rutrum est elat vistibulum eu."; // Atât „elit” cât și „elat” vor face. Punctul înseamnă că orice simbol va funcționa. var regex = /el.t/g; console.log(text.match(regex)); // „est” și „lest” vor funcționa la fel de bine. Semnul întrebării face ca „l” să fie opțional. var regex2 = /l?est/g; console.log(text.match(regex2));

var text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit lest. Donec convallis dignissim ligula, et rutrum est elat vistibulum eu.";

// Atât „elit” cât și „elat” vor face. Punctul înseamnă că orice simbol va funcționa.

var regex = /el.t/g ;

consolă. log(text. potrivire(regex));

// „est” și „lest” vor funcționa la fel de bine. Semnul întrebării face „l” opțional.

var regex2 = /l?est/g ;

consolă. log(text. potrivire(regex2));

Potriviți mai multe personaje

Un set este unul sau mai multe caractere cuprinse între paranteze, de exemplu . O astfel de expresie va căuta numai acest set de caractere dintr-un șir - in în acest exemplu doar a, b sau c. Dimpotrivă, puteți căuta aparițiile oricărui simbol, cu excepția utilizării simbolului „^”. [^abc] se va potrivi cu orice caracter care nu este a, b sau c. De asemenea, puteți specifica o serie de caractere sau numere, de exemplu , .

Există seturi de caractere încorporate care facilitează scrierea expresiilor regulate. Ele sunt numite abrevieri sau stenografie. De exemplu, puteți scrie \D în schimb. Există abrevieri pentru alte caractere (inclusiv numere și caractere de subliniere) - \w și \W, precum și pentru spații - \s și \S.

// Numai „pisica” și „poate” vor funcționa, nu „mașină”. var text = „cu mașină pisică”; console.log(text.match(/ca/g)); // Totul va trece, cu excepția pisicii și a can (există un simbol ^) console.log(text.match(/ca[^tn]/g)); // Un alt exemplu în care doar numerele vor trece text = „Aș dori 8 cești de cafea, te rog.”; console.log("Câte cești: " + text.match(//g)); // Mod mai simplu folosind comanda rapidă \d console.log("Câte cupe: " + text.match(/\d/g)); // Trece totul, cu excepția numerelor console.log(text.match(/\D/g));

// Numai „pisica” și „poate” vor funcționa, nu „mașină”.

var text = "cu mașină cu pisică" ;

consolă. log(text. potrivire(/ca/g));

// Trece totul, în afară de pisică și poate (există un simbol ^)

consolă. jurnal (text . potrivire (/ca[^tn]/g ) ) ;

// Un alt exemplu în care vor trece numai numere

text = "Aș dori 8 căni de cafea, te rog.";

consolă. jurnal ("Câte cești: " + text . potrivi (//g ) ) ;

// Mod mai simplu folosind comanda rapidă \d

consolă. log("Câte cești: " + text . potriviți (/\d/g ) ) ;

// Totul va trece cu excepția numerelor

consolă. log(text. potrivire(/\D/g));

Cuvinte potrivite

În cele mai multe cazuri, trebuie să cauți mai degrabă cuvinte întregi decât personaje individuale. Acest lucru se face folosind modificatori (+) și (-), care repetă un caracter sau un set de caractere.

Adăugarea (X) specifică numărul exact de repetări, (x, y) – intervalul (x și y sunt numere).

În plus, există un model special \b care se potrivește cu granițele de la sfârșitul cuvintelor.

var text = "Bună ziua, oamenii anului 1974. Vin din viitor. În 2014 avem pistoale laser, plăci hover și trăim pe lună!"; // Voi găsi ani. \d+ se va potrivi cu unul sau mai multe caractere var yearRegex = /\d+/g; console.log("Ani: ", text.match(yearRegex)); // Găsește toate propozițiile. Propozițiile noastre încep cu o literă mare și se termină cu un punct sau un semn de exclamare. var sentenceRegex = /.+?(\.|!)/g; console.log("Propoziții: ", text.match(sentenceRegex)); // Găsește toate cuvintele care încep cu „h”. Atât majuscule, cât și litere mici sunt potrivite pentru noi, așa că folosim modificatorul i // \b pentru a defini limita cuvântului. var hWords = /\bh\w+/ig; console.log("H Words: ", text.match(hWords)); // Găsește toate cuvintele de la 4 la 6 caractere var findWords = /\b\w(4,6)\b/g; console.log("Cuvinte între 4 și 6 caractere: ", text.match(findWords)); // Găsiți cuvinte mai lungi de 5 caractere console.log("Cuvinte de 5 caractere sau mai lungi: ", text.match(/\b\w(5,)\b/g)); // Găsește cuvinte cu exact 6 caractere lungi console.log("Cuvinte cu exact 6 caractere lungi: ", text.match(/\b\w(6)\b/g));

var text = "Bună ziua, oameni din 1974. Vin din viitor. În 2014 avem pistoale laser, plăci hover și trăim pe Lună!";

// Voi găsi ani. \d+ se potrivește cu unul sau mai multe caractere

var yearRegex = /\d+/g ;

consolă. log ("Anii: " , text . potrivire ( yearRegex ) ) ;

// Găsește toate propozițiile. Propozițiile noastre încep cu o literă mare și se termină cu un punct sau un semn de exclamare.

var sentenceRegex = /.+?(\.|!)/g ;

consolă. log("Propoziții: ", text. potrivire(propozițieRegex));

// Găsește toate cuvintele care încep cu „h”. Atât majuscule, cât și litere mici sunt potrivite pentru noi, așa că folosim modificatorul i

// \b pentru a determina limitele cuvintelor.

var hWords = /\bh\w+/i g ;

consolă. jurnal ("H Words: " , text . match ( hWords ) ) ;

// Găsește toate cuvintele de la 4 la 6 caractere

var findWords = /\b\w(4,6)\b/g ;

consolă. Buturuga( "Cuvinte între 4 și 6 caractere: ", text . potrivire(găsi cuvinte));

// Găsiți cuvinte mai lungi de 5 caractere

consolă. jurnal ("Cuvinte de 5 caractere sau mai mult: " , text . potrivire (/\b\w(5,)\b/g ) ) ;

// Găsiți cuvinte cu exact 6 caractere lungime

consolă. Buturuga( „Cuvintele cu exact 6 caractere lungi:”, text . potrivire (/\b\w(6)\b/g ) );

Validarea întregului șir

În JavaScript, astfel de expresii pot fi folosite pentru a valida introducerea utilizatorului din câmpurile de text. Pentru validarea șirurilor de caractere se folosește o expresie regulată regulată, legată de începutul și sfârșitul unui fragment de text, folosind expresiile ^ (început de linie) și $ (sfârșit de linie) în acest scop. Aceste simboluri asigură că modelul pe care îl scrieți se întinde pe întreaga lungime a textului și nu se potrivește doar cu o parte a acestuia.

În plus, în acest caz, folosim metoda test() a obiectului regex, care returnează adevărat sau fals atunci când testăm dacă expresia regulată se potrivește cu șirul.

// Avem o serie de șiruri de caractere, să găsim link-uri..com/", "123461", "https://site/?s=google", "http://nu este un URL valid", "abc http: / /invalid.url/" ]; var regex = /^https?:\/\/[\w\/?.&-=]+$/; var URL = ; for(var i = 0; i< strings.length; i++){ if(regex.test(strings[i])){ // Валидная ссылка urls.push(strings[i]); } } console.log("Valid URLs: ", urls);

// Avem o serie de șiruri, haideți să găsim link-urile.

var șiruri = [

„https://site/”,

„aceasta nu este o adresă URL”,

„https://google.com/”,

"123461" ,

„https://site/?s=google” ,

„http://nu este o adresă URL validă”,

„abc http://invalid.url/”

var regex = / ^ https ? : \ / \ / [ \ w \ / ? . & -= ] + $ / ;

var URL = ;

pentru (var i = 0; i< strings . length ; i ++ ) {

if (regex. test (șiruri [i])) (

URL-uri. împinge(șiruri[i]);

consolă. log("Adrese URL valide: ", URL);

Căutați și înlocuiți

O altă sarcină comună care este simplificată prin utilizarea expresiilor regulate este găsirea și înlocuirea textului.

Expresii obisnuite

Expresie uzuala este un obiect care descrie un model de caracter. Clasa RegExp din JavaScript reprezintă expresii regulate, iar obiectele clasei String și RegExp definesc metode care folosesc expresii regulate pentru a efectua potrivirea modelelor și operațiunile de căutare și înlocuire a textului. Gramatica expresiei regulate JavaScript conține un subset destul de complet al sintaxei expresiilor regulate folosită în Perl 5, așa că dacă aveți experiență cu Perl, puteți scrie cu ușurință modele în programele JavaScript.

Caracteristicile expresiilor regulate Perl care nu sunt acceptate în ECMAScript includ steagurile s (modul cu o singură linie) și x (sintaxă extinsă); secvențe de evacuare \a, \e, \l, \u, \L, \U, \E, \Q, \A, \Z, \z și \G și alte constructe extinse care încep cu (?.

Definirea expresiilor regulate

ÎN JavaScript obișnuit expresiile sunt reprezentate de obiecte RegExp. Obiectele RegExp pot fi create folosind constructorul RegExp(), dar mai des sunt create folosind o sintaxă literală specială. Așa cum literalele șir sunt specificate ca caractere înconjurate de ghilimele, literalele expresii regulate sunt specificate ca caractere înconjurate de o pereche de caractere bară oblică (/). Deci, codul dvs. JavaScript poate conține linii ca aceasta:

Var model = /s$/;

Această linie creează un nou obiect RegExp și îl atribuie variabilei de tipar. Acest obiect RegExp caută orice șir care se termină cu caracterul „s”. Aceeași expresie regulată poate fi definită folosind constructorul RegExp():

Var model = new RegExp("s$");

O specificație de model de expresie regulată constă dintr-o secvență de caractere. Majoritatea personajelor, inclusiv toate caracterele alfanumerice, descriu literalmentele care trebuie să fie prezente. Adică, expresia regulată /java/ se potrivește cu toate liniile care conțin subșirul „java”.

Alte caractere din expresiile regulate nu sunt destinate să fie folosite pentru a-și găsi echivalentele exacte, ci mai degrabă au semnificații speciale. De exemplu, expresia regulată /s$/ conține două caractere. Primul caracter s denotă o căutare a unui caracter literal. În al doilea rând, $ este un metacaracter special care marchează sfârșitul unei linii. Deci această expresie regulată se potrivește cu orice șir care se termină cu caracterul s.

Următoarele secțiuni descriu diferitele caractere și metacaractere utilizate în expresiile regulate în JavaScript.

Personaje literale

După cum sa menționat mai devreme, toate caracterele alfabetice și numerele din expresiile regulate se potrivesc. Sintaxa expresiilor regulate în JavaScript acceptă, de asemenea, capacitatea de a specifica anumite caractere non-alfabetice folosind secvențe de evacuare care încep cu un caracter backslash (\). De exemplu, secvența \n se potrivește cu caracterul newline. Aceste simboluri sunt enumerate în tabelul de mai jos:

Unele semne de punctuație au semnificații speciale în expresiile regulate:

^ $ . * + ? = ! : | \ / () { } -

Semnificația acestor simboluri este explicată în secțiunile următoare. Unele dintre ele au o semnificație specială doar în anumite contexte de expresie regulată, în timp ce în alte contexte sunt interpretate literal. Cu toate acestea, în general, pentru a include literalmente oricare dintre aceste caractere într-o expresie obișnuită, trebuie să îl precedați cu un caracter backslash. Alte caractere, cum ar fi ghilimele și @, nu au o semnificație specială și pur și simplu se potrivesc în expresii regulate.

Dacă nu vă amintiți exact ce caractere ar trebui să fie precedate de un \, puteți pune în siguranță o bară oblică inversă în fața oricărui caracter. Cu toate acestea, rețineți că multe litere și numere capătă semnificații speciale atunci când sunt combinate cu caracterul oblic, astfel încât literele și numerele pe care le căutați literalmente nu trebuie să fie precedate de un caracter \. Pentru a include caracterul bară oblică inversă în sine într-o expresie obișnuită, trebuie în mod evident să îl precedați cu un alt caracter bară oblică inversă. De exemplu, următoarea expresie regulată se potrivește cu orice șir care conține un caracter bară oblică inversă: /\\/.

Clasele de caractere

Caracterele literale individuale pot fi combinate în clase de caractere prin includerea lor între paranteze drepte. O clasă de caractere se potrivește cu orice caracter conținut în acea clasă. Prin urmare, expresia regulată // se potrivește cu unul dintre caracterele a, b sau c.

Clasele de caractere negative pot fi, de asemenea, definite pentru a se potrivi cu orice caracter, cu excepția celor specificate în paranteze. Clasa de caractere de negație este specificată de caracterul ^ ca primul caracter după paranteza din stânga. Expresia regulată /[^abc]/ se potrivește cu orice alt caracter decât a, b sau c. În clasele de caractere, o serie de caractere poate fi specificată folosind o cratimă. Toate caracterele latine litere mici sunt găsite folosind expresia //, iar orice literă sau număr din setul de caractere latine poate fi găsită folosind expresia //.

Anumite clase de caractere sunt deosebit de comune, astfel încât sintaxa expresiilor regulate în JavaScript include caractere speciale și secvențe de escape pentru a le reprezenta. Astfel, \s se potrivește cu spațiul, tabulatorul și orice caractere de spațiu alb Unicode, iar \S se potrivește cu orice caractere de spațiu alb non-Unicode.

Tabelul de mai jos oferă o listă a acestor caractere speciale și sintaxa claselor de caractere. (Rețineți că unele dintre secvențele de escape ale clasei de caractere se potrivesc numai cu caractere ASCII și nu sunt extinse pentru a funcționa cu caractere Unicode. Puteți defini în mod explicit propriile clase de caractere Unicode, de exemplu /[\u0400-\u04FF]/ se potrivește cu orice caracter alfabet chirilic .)

Clase de caractere cu expresii regulate JavaScript
Simbol Corespondenţă
[...] Oricare dintre caracterele afișate în paranteze
[^...] Oricare dintre caracterele care nu sunt enumerate în paranteze
. Orice caracter, altul decât o nouă linie sau alt delimitator de linie Unicode
\w Orice caracter text ASCII. Echivalent
\W Orice caracter care nu este un caracter text ASCII. Echivalent cu [^a-zA-Z0-9_]
\s Orice caracter de spațiu alb din setul Unicode
\S Orice caracter fără spații albe din setul Unicode. Vă rugăm să rețineți că caracterele \w și \S nu sunt același lucru
\d Orice numere ASCII. Echivalent
\D Orice caracter altul decât numerele ASCII. Echivalent cu [^0-9]
[\b] Literal caracter înapoi

Rețineți că secvențele de evacuare caractere speciale clasele pot fi între paranteze drepte. \s se potrivește cu orice caracter de spațiu alb și \d se potrivește cu orice cifră, prin urmare /[\s\d]/ se potrivește cu orice caracter de spațiu alb sau cifră.

Repetiţie

Având în vedere cunoștințele despre sintaxa expresiilor regulate acumulate până acum, putem descrie un număr din două cifre ca /\d\d/ sau un număr din patru cifre ca /\d\d\d\d/, dar nu putem, de exemplu , descrieți un număr format din orice număr de cifre sau un șir de trei litere urmat de o cifră opțională. Aceste modele mai complexe folosesc sintaxa expresiei regulate, care specifică de câte ori poate fi repetat un anumit element de expresie regulată.

Simbolurile repetate urmează întotdeauna modelul la care sunt aplicate. Unele tipuri de repetări sunt folosite destul de des și sunt disponibile simboluri speciale pentru a indica aceste cazuri. De exemplu, + se potrivește cu una sau mai multe instanțe ale modelului anterior. Următorul tabel oferă un rezumat al sintaxei repetiției:

Următoarele rânduri prezintă câteva exemple:

Var model = /\d(2,4)/; // Potrivește un număr care conține două până la patru cifre model = /\w(3)\d?/; // Potriviți exact trei caractere de cuvinte și un model de cifre opțional = /\s+java\s+/; // Potrivește cuvântul „java” cu unul sau mai multe spații // înainte și după model = /[^(]*/; // Potrivește zero sau mai multe caractere, altele decât paranteza de deschidere

Aveți grijă când utilizați caractere repetate * și ?. Se pot potrivi cu absența unui model specificat înaintea lor și, prin urmare, cu absența caracterelor. De exemplu, expresia regulată /a*/ se potrivește cu șirul „bbbb” deoarece nu conține caracterul a.

Caracterele de repetiție enumerate în tabel reprezintă numărul maxim posibil de repetări care va permite potrivirea părților ulterioare ale expresiei regulate. Spunem că aceasta este o repetiție lacomă. De asemenea, este posibil să implementați repetarea într-o manieră non-lacomă. Este suficient să indicați după simbol (sau simboluri) repetarea semnul întrebării: ??, +?, *? sau chiar (1,5)?.

De exemplu, expresia regulată /a+/ se potrivește cu una sau mai multe instanțe ale literei a. Când este aplicat șirului „aaa”, se potrivește cu toate cele trei litere. Pe de altă parte, expresia /a+?/ se potrivește cu una sau mai multe instanțe ale literei a și selectează cel mai puțin posibil număr de caractere. Aplicat aceluiași șir, acest model se potrivește doar cu prima literă a.

Repetarea „fără lăcomie” nu dă întotdeauna rezultatul așteptat. Luați în considerare modelul /a+b/, care se potrivește cu unul sau mai multe a urmate de b. Când este aplicat șirului „aaab”, acesta corespunde întregului șir.

Acum să verificăm versiunea „non-lacomă” a lui /a+?b/. S-ar putea crede că s-ar potrivi cu un b precedat doar de unul a. Dacă se aplică aceluiași șir, se așteaptă ca „aaab” să se potrivească cu singurul caracter a și ultimul caracter b. Cu toate acestea, acest model se potrivește de fapt cu întregul șir, la fel ca versiunea lacomă. Faptul este că o căutare a modelului de expresie regulată se realizează prin găsirea primei poziții în șir, începând de la care o potrivire devine posibilă. Deoarece o potrivire este posibilă începând de la primul caracter al șirului, potrivirile mai scurte începând de la caracterele ulterioare nici măcar nu sunt luate în considerare.

Alternative, grupări și legături

Gramatica expresiilor regulate include caractere speciale pentru definirea alternativelor, gruparea subexpresiilor și referințe la subexpresiile anterioare. Simbol țeavă | servește la separarea alternativelor. De exemplu, /ab|cd|ef/ se potrivește fie cu șirul „ab”, fie cu șirul „cd”, fie cu șirul „ef”, iar modelul /\d(3)|(4)/ se potrivește fie cu trei cifre sau patru litere mici .

Rețineți că alternativele sunt procesate de la stânga la dreapta până când este găsită o potrivire. Dacă se găsește o potrivire cu alternativa din stânga, cea din dreapta este ignorată, chiar dacă se poate obține o potrivire „mai bună”. Prin urmare, atunci când modelul /a|ab/ este aplicat șirului „ab”, acesta se va potrivi doar cu primul caracter.

Parantezele au semnificații multiple în expresiile regulate. Una dintre ele este gruparea elemente individualeîntr-o singură subexpresie, astfel încât elementele atunci când se folosesc caracterele speciale |, *, +, ? iar altele sunt considerate ca un întreg. De exemplu, modelul /java(script)?/ se potrivește cu cuvântul „java” urmat de cuvântul opțional „script”, iar /(ab|cd)+|ef)/ se potrivește fie cu șirul „ef”, fie cu unul sau mai multe repetări ale unuia din șirurile „ab” sau „cd”.

O altă utilizare a parantezelor în expresiile regulate este definirea subpatternelor într-un model. Când se găsește o potrivire a expresiei regulate în șirul țintă, porțiunea din șirul țintă care se potrivește cu orice submodel specific inclus în paranteze poate fi extrasă.

Să presupunem că doriți să găsiți una sau mai multe litere mici urmate de unul sau mai multe numere. Pentru a face acest lucru, puteți utiliza șablonul /+\d+/. Dar să presupunem și că vrem doar numerele de la sfârșitul fiecărui meci. Dacă punem această parte a modelului între paranteze (/+(\d+)/), putem extrage numere din orice potrivire pe care le găsim. Cum se face acest lucru va fi descris mai jos.

O utilizare înrudită a subexpresiilor între paranteze este de a se referi la subexpresii dintr-o parte anterioară a aceleiași expresii regulate. Acest lucru se realizează prin specificarea uneia sau mai multor cifre după caracterul \. Numerele se referă la poziția subexpresiei între paranteze în cadrul expresiei regulate. De exemplu, \1 se referă la prima subexpresie, iar \3 se referă la a treia. Rețineți că subexpresiile pot fi imbricate una în cealaltă, astfel încât poziția parantezei din stânga este utilizată la numărare. De exemplu, în următoarea expresie regulată, o referință de subexpresie imbricată (script) ar arăta ca \2:

/(ava(script)?)\sis\s(fun\w*)/

O referire la o subexpresie anterioară nu indică modelul acelei subexpresii, ci textul găsit care se potrivește cu acel model. Prin urmare, referințele pot fi folosite pentru a impune o constrângere care selectează părți dintr-un șir care conțin exact aceleași caractere. De exemplu, următoarea expresie regulată se potrivește cu zero sau mai multe caractere între ghilimele simple sau duble. Cu toate acestea, nu necesită ca ghilimelele de deschidere și de închidere să se potrivească între ele (adică ca ambele ghilimele să fie simple sau duble):

/[""][^""]*[""]/

Putem solicita ca ghilimele să se potrivească folosind o referință ca aceasta:

Aici \1 se potrivește cu prima subexpresie. În acest exemplu, legătura impune o constrângere care necesită ca ghilimelele de închidere să se potrivească cu ghilimelele de deschidere. Această expresie regulată nu permite ghilimele simple în ghilimele duble și invers.

De asemenea, este posibil să grupați elemente într-o expresie regulată fără a crea o referință numerotată la acele elemente. În loc să grupați pur și simplu elementele între ( și ), începeți grupul cu simboluri (?: și terminați-l cu un simbol). Luați în considerare, de exemplu, următorul model:

/(ava(?:script)?)\sis\s(fun\w*)/

Aici subexpresia (?:script) este necesară doar pentru grupare, astfel încât caracterul de repetiție să poată fi aplicat grupului. Aceste paranteze modificate nu creează o legătură, așa că în această expresie regulată, \2 se referă la text care se potrivește cu modelul (distracție\w*).

Următorul tabel listează operatorii de selecție, grupare și referință în expresii regulate:

Selectarea JavaScript, gruparea și linkul simbolurilor expresiilor regulate
Simbol Sens
| Alternativă. Se potrivește fie cu subexpresia din stânga, fie cu subexpresia din dreapta.
(...) Gruparea. Grupează elemente într-o singură unitate care poate fi folosită cu caracterele *, +, ?, | și așa mai departe. De asemenea, își amintește caracterele care se potrivesc cu acest grup pentru a fi utilizate în referințele ulterioare.
(?:...) Doar grupare. Grupează elemente într-o singură unitate, dar nu își amintește caracterele care corespund grupului respectiv.
\număr Se potrivește cu aceleași caractere care au fost găsite la potrivirea numărului de grup. Grupurile sunt subexpresii în paranteze (eventual imbricate). Numerele grupurilor sunt atribuite numărând parantezele din stânga de la stânga la dreapta. Grupurile formate folosind simbolurile (?:) nu sunt numerotate.

Specificarea poziţiei de potrivire

După cum sa descris mai devreme, multe elemente ale unei expresii regulate se potrivesc cu un singur caracter dintr-un șir. De exemplu, \s se potrivește cu un singur caracter de spațiu alb. Alte elemente de expresie regulată se potrivesc mai degrabă cu pozițiile dintre caractere decât cu caracterele în sine. De exemplu, \b se potrivește cu o graniță a unui cuvânt — limita dintre \w (un caracter text ASCII) și \W (un caracter non-text) sau limita dintre un caracter text ASCII și începutul sau sfârșitul unei linii.

Elemente precum \b nu specifică niciun caracter care trebuie să fie prezent în șirul potrivit, dar specifică poziții valide pentru potrivire. Aceste elemente sunt uneori numite elemente de ancorare a expresiei regulate, deoarece ancorează modelul într-o anumită poziție din șir. Cele mai frecvent utilizate elemente de ancorare sunt ^ și $, care leagă modelele la începutul și, respectiv, la sfârșitul unei linii.

De exemplu, cuvântul „JavaScript” pe propria linie poate fi găsit folosind expresia regulată /^JavaScript$/. A găsi cuvânt separat„Java” (mai degrabă decât un prefix, cum ar fi cuvântul „JavaScript”), puteți încerca să utilizați modelul /\sJava\s/, care necesită un spațiu înainte și după cuvânt.

Dar o astfel de soluție ridică două probleme. În primul rând, va găsi cuvântul „Java” doar dacă este înconjurat de spații pe ambele părți și nu îl va putea găsi la începutul sau la sfârșitul liniei. În al doilea rând, când acest model se potrivește, șirul pe care îl returnează va conține spații de început și de final, ceea ce nu este exact ceea ce ne dorim. Deci, în loc să folosim un model care se potrivește cu caracterele de spațiu alb \s, vom folosi un model (sau ancora) care se potrivește cu granițele cuvintelor \b. Rezultatul va fi următoarea expresie: /\bJava\b/.

Elementul ancora \B se potrivește cu o poziție care nu este o limită de cuvânt. Adică, modelul /\BScript/ se va potrivi cu cuvintele „JavaScript” și „postscript” și nu se va potrivi cu cuvintele „script” sau „Scripting”.

Expresiile regulate arbitrare pot servi și ca condiții de ancorare. Dacă plasați o expresie între caractere (?= și), aceasta devine un test de potrivire înainte cu caracterele ulterioare, necesitând ca acele caractere să se potrivească cu modelul specificat, dar să nu fie incluse în șirul de potrivire.

De exemplu, pentru a potrivi numele unui limbaj de programare comun urmat de două puncte, puteți utiliza expresia /ava(script)?(?=\:)/. Acest model se potrivește cu cuvântul „JavaScript” din șirul „JavaScript: The Definitive Guide”, dar nu se va potrivi cu cuvântul „Java” din șirul „Java pe scurt”, deoarece nu este urmat de două puncte.

Dacă introduceți condiția (?!), atunci aceasta va fi o verificare negativă înainte pentru caracterele ulterioare, necesitând ca următoarele caractere să nu se potrivească cu modelul specificat De exemplu, modelul /Java(?!Script)(\w*. )/ se potrivește cu subșirul „Java”, urmat de majusculăși orice număr de caractere text ASCII, cu condiția ca subșirul „Java” să nu fie urmat de subșirul „Script”. Se va potrivi cu șirul „JavaBeans”, dar nu și cu șirul „Javanese”, și se va potrivi cu șirul „JavaScrip”, dar nu și cu șirurile „JavaScript” sau „JavaScripter”.

Tabelul de mai jos oferă o listă de caractere de ancorare a expresiei regulate:

Caractere ancoră expresii regulate
Simbol Sens
^ Potrivește începutul unei expresii șir sau începutul unei linii într-o căutare pe mai multe linii.
$ Se potrivește la sfârșitul unei expresii șir sau la sfârșitul unei linii într-o căutare pe mai multe linii.
\b Se potrivește cu o limită de cuvânt, de ex. potrivește poziția dintre un caracter \w și un caracter \W sau între un caracter \w și începutul sau sfârșitul unei linii. (Rețineți, totuși, că [\b] se potrivește cu caracterul backspace.)
\B Se potrivește cu o poziție care nu este o limită de cuvânt.
(?=p) Verificare anticipată pozitivă pentru caracterele ulterioare. Necesită caractere ulterioare pentru a se potrivi cu modelul p, dar nu include acele caractere în șirul potrivit.
(?!p) Verificare înainte negativă pentru caracterele ulterioare. Necesită ca următoarele caractere să nu se potrivească cu modelul p.

Steaguri

Și un ultim element al gramaticii expresiilor regulate. Indicatoarele de expresie regulată specifică reguli de potrivire a modelelor de nivel înalt. Spre deosebire de restul gramaticii expresiilor regulate, steagurile sunt specificate nu între caracterele oblice, ci după al doilea. JavaScript acceptă trei steaguri.

Steagul i specifică că potrivirea modelului ar trebui să nu țină seama de majuscule și minuscule și steag g- că căutarea să fie globală, adică trebuie găsite toate potrivirile din șir. Steagul m efectuează o căutare de model în modul cu mai multe linii. Dacă expresia șir căutată conține linii noi, atunci în acest mod caracterele ancora ^ și $, pe lângă potrivirea începutului și sfârșitului întregii expresii șirului, potrivesc și începutul și sfârșitul fiecărei șir de text. De exemplu, modelul /java$/im se potrivește atât cu „java” cât și cu „Java\nis fun”.

Aceste steaguri pot fi combinate în orice combinație. De exemplu, pentru a căuta prima apariție a cuvântului „java” (sau „Java”, „JAVA”, etc.) fără a ține seama de majuscule și minuscule, puteți utiliza expresia regulată care nu ține seama de majuscule și minuscule /\bjava\b/ i. Și pentru a găsi toate aparițiile acestui cuvânt într-un șir, puteți adăuga steag-ul g: /\bjava\b/gi.

Metode ale clasei String pentru căutarea după model

Până în acest moment, am discutat despre gramatica expresiilor regulate pe care le creăm, dar nu ne-am uitat la modul în care aceste expresii regulate pot fi de fapt utilizate în scripturile JavaScript. ÎN aceasta sectiune Vom discuta despre metodele obiectului String care folosesc expresii regulate pentru potrivirea modelelor, precum și căutarea cu înlocuire. Și apoi vom continua conversația despre potrivirea modelelor cu expresii regulate, uitându-ne la obiectul RegExp și la metodele și proprietățile acestuia.

Strings acceptă patru metode folosind expresii regulate. Cea mai simplă dintre ele este metoda căutare(). Ia o expresie regulată ca argument și returnează fie poziția primului caracter al subșirului potrivit, fie -1 dacă nu se găsește nicio potrivire. De exemplu, următorul apel va returna 4:

Var rezultat = "JavaScript".search(/script/i); // 4

Dacă argumentul metodei search() nu este o expresie regulată, acesta este mai întâi convertit prin trecerea acestuia către constructorul RegExp. Metoda search() nu acceptă căutarea globală și ignoră indicatorul g din argumentul său.

Metodă a inlocui() efectuează o operație de căutare și înlocuire. Ia o expresie regulată ca prim argument și un șir de înlocuire ca al doilea. Metoda caută pe linia pe care este apelată o potrivire cu modelul specificat.

Dacă expresia regulată conține indicatorul g, metoda replace() înlocuiește toate potrivirile găsite cu șirul de înlocuire. În caz contrar, înlocuiește doar prima potrivire găsită. Dacă primul argument al metodei replace() este un șir mai degrabă decât o expresie regulată, atunci metoda efectuează o căutare literală pentru șir, mai degrabă decât să-l convertească într-o expresie regulată folosind constructorul RegExp() așa cum o face metoda search().

Ca exemplu, putem folosi metoda replace() pentru a scrie cu majuscule cuvântul „JavaScript” în mod constant pe o linie întreagă de text:

// Indiferent de caractere, le înlocuim cu un cuvânt în cazul necesar var result = "javascript".replace(/JavaScript/ig, "JavaScript");

Metoda replace() este mai mult Unealtă puternică decât ar sugera acest exemplu. Permiteți-mi să vă reamintesc că subexpresiile din paranteze din cadrul unei expresii regulate sunt numerotate de la stânga la dreapta și că expresia regulată își amintește textul corespunzător fiecărei subexpresii. Dacă șirul de înlocuire conține un semn $ urmat de un număr, metoda replace() înlocuiește acele două caractere cu textul care se potrivește cu subexpresia specificată. Aceasta este foarte oportunitate utila. Îl putem folosi, de exemplu, pentru a înlocui ghilimele drepte dintr-un șir cu ghilimele tipografice, care sunt simulate cu caractere ASCII:

// Un citat este un citat urmat de orice număr de caractere // altele decât ghilimele (pe care le amintim), urmate de un alt citat // var citat = /"([^"]*)"/g; // Înlocuiește ghilimele drepte cu cele tipografice și lasă „$1” neschimbat // conținutul citatului stocat în $1 var text = ""JavaScript" este un limbaj de programare interpretat."; var result = text.replace(quote, ""$1""; ) ; // "JavaScript" este un limbaj de programare interpretat.

Un lucru important de remarcat este că al doilea argument pentru înlocuire() poate fi o funcție care calculează dinamic șirul de înlocuire.

Metodă Meci()- aceasta este cea mai comună dintre metode clasa String folosind expresii regulate. Acesta ia o expresie regulată ca singur argument (sau își convertește argumentul într-o expresie regulată, pasând-o la constructorul RegExp()) și returnează o matrice care conține rezultatele căutării. Dacă indicatorul g este setat în expresia regulată, metoda returnează o matrice cu toate potrivirile prezente în șir. De exemplu:

// va returna ["1", "2", "3"] var rezultat = "1 plus 2 equals 3".match(/\d+/g);

Dacă expresia regulată nu conține indicatorul g, metoda match() nu efectuează o căutare globală; caută doar primul meci. Totuși, match() returnează o matrice chiar și atunci când metoda nu efectuează o căutare globală. În acest caz, primul element al tabloului este subșirul găsit, iar toate elementele rămase sunt subexpresii ale expresiei regulate. Deci, dacă match() returnează o matrice arr, atunci arr va conține întregul șir găsit, arr subșirul corespunzător primei subexpresii etc. Făcând o paralelă cu metoda replace(), putem spune că conținutul lui $n este introdus în arr[n].

De exemplu, aruncați o privire la următoarele codul programului care analizează adresa URL:

Var url = /(\w+):\/\/([\w.]+)\/(\S*)/; var text = "Vizitați site-ul nostru http://www..php"; var rezultat = text.match(url); if (rezultat != null) ( var fullurl = rezultat; // Conține „http://www..php” var protocol = rezultat; // Conține „http” var gazdă = rezultat; // Conține „www..php” " )

Trebuie remarcat faptul că pentru o expresie regulată care nu are steag-ul g setat căutare globală, metoda match() returnează aceeași valoare ca metoda exec() a expresiei regulate: tabloul returnat are proprietăți de index și de intrare, așa cum este descris în discuția despre metoda exec() de mai jos.

Ultima dintre metodele obiect String care utilizează expresii regulate este Despică(). Această metodă împarte șirul pe care este apelat într-o matrice de subșiruri, folosind argumentul ca delimitator. De exemplu:

"123.456.789".split(","); // Întoarce ["123","456","789"]

Metoda split() poate lua, de asemenea, o expresie regulată ca argument. Acest lucru face metoda mai puternică. De exemplu, puteți specifica un delimitator care permite un număr arbitrar de caractere spații albe pe ambele părți:

„1, 2, 3 , 4 , 5”.split(/\s*,\s*/); // Întoarce ["1","2","3","4","5"]

obiect RegExp

După cum sa menționat, expresiile regulate sunt reprezentate ca obiecte RegExp. În plus față de constructorul RegExp(), obiectele RegExp acceptă trei metode și mai multe proprietăți.

Constructorul RegExp() preia unul sau două argumente șir și creează un nou obiect RegExp. Primul argument al constructorului este un șir care conține corpul expresiei regulate, i.e. text care trebuie să apară între caracterele bară oblică într-o expresie regulată literală. Rețineți că literalele șir și expresiile regulate folosesc caracterul \ pentru a reprezenta secvențele de evadare, așa că atunci când treceți expresia regulată ca un literal șir către constructorul RegExp(), trebuie să înlocuiți fiecare caracter \ cu o pereche de caractere \\.

Al doilea argument pentru RegExp() poate lipsi. Dacă este specificat, definește steagurile expresiilor regulate. Trebuie să fie unul dintre caracterele g, i, m sau o combinație a acestor caractere. De exemplu:

// Găsește toate numerele de cinci cifre dintr-un șir. Notă // utilizarea simbolurilor în acest exemplu \\ var zipcode = new RegExp("\\d(5)", "g");

Constructorul RegExp() este util atunci când expresia regulată este generată dinamic și, prin urmare, nu poate fi reprezentată folosind sintaxa literală a expresiei regulate. De exemplu, pentru a găsi un șir introdus de utilizator, trebuie să creați o expresie regulată în timpul execuției folosind RegExp().

Proprietăți RegExp

Fiecare obiect RegExp are cinci proprietăți. Proprietate sursă- un șir numai pentru citire care conține textul expresiei regulate. Proprietate global este o valoare booleană numai pentru citire care specifică dacă indicatorul g este prezent în expresia regulată. Proprietate ignoreCase este o valoare booleană numai pentru citire care determină dacă steag-ul i este prezent în expresia regulată. Proprietate multilinie este o valoare booleană numai pentru citire care determină dacă indicatorul m este prezent în expresia regulată. Și ultima proprietate ultimulIndex este un număr întreg care poate fi citit și scris. Pentru modelele cu steag g, această proprietate conține numărul de poziție în linia la care ar trebui să înceapă următoarea căutare. După cum este descris mai jos, este utilizat de metodele exec() și test().

Metode RegExp

Obiectele RegExp definesc două metode care efectuează potrivirea modelelor; ele se comportă similar cu metodele clasei String descrise mai sus. Metoda principală a clasei RegExp utilizată pentru potrivirea modelelor este exec(). Este similar cu metoda match() menționată anterior a clasei String, cu excepția faptului că este o metodă de clasă RegExp care ia un șir ca argument, mai degrabă decât o metodă de clasă String care ia un argument RegExp.

Metoda exec() execută expresia regulată pentru șirul specificat, adică. caută o potrivire într-un șir. Dacă nu se găsește nicio potrivire, metoda returnează null. Totuși, dacă se găsește o potrivire, returnează aceeași matrice ca și matricea returnată de metoda match() pentru căutarea fără indicatorul g. Element zero Matricea conține un șir care se potrivește cu expresia regulată, iar toate elementele ulterioare sunt subșiruri care se potrivesc cu toate subexpresiile. În plus, proprietatea index conține numărul de poziție al caracterului cu care începe fragmentul corespunzător și proprietatea intrare se referă la linia care a fost căutată.

Spre deosebire de match(), metoda exec() returnează un tablou a cărui structură nu depinde de prezența steagului g în expresia regulată. Permiteți-mi să vă reamintesc că atunci când treceți o expresie regulată globală, metoda match() returnează o serie de potriviri găsite. Și exec() returnează întotdeauna o potrivire, dar oferă informații despre aceasta informatii complete. Când exec() este apelat pe o expresie regulată care conține indicatorul g, metoda setează proprietatea lastIndex a obiectului expresie regulată la numărul de poziție al caracterului imediat după subșirul găsit.

Când exec() este apelat a doua oară pe aceeași expresie regulată, începe căutarea la caracterul a cărui poziție este specificată în proprietatea lastIndex. Dacă exec() nu găsește o potrivire, proprietatea lastIndex este setată la 0. (Puteți, de asemenea, să setați lastIndex la zero în orice moment, ceea ce ar trebui făcut în toate cazurile în care căutarea se termină înainte ca ultima potrivire dintr-un singur rând să fie găsit, iar căutarea începe pe o altă linie cu același obiect RegExp.) Acest comportament special permite apelarea exec() în mod repetat pentru a repeta peste toate potrivirile expresiilor regulate din linie. De exemplu:

Var model = /Java/g; var text = "JavaScript este mai mult lucru amuzant decât Java!"; var rezultat; while((rezultat = pattern.exec(text)) != null) ( console.log("Găsit "" + rezultat + """ + " la poziția " + result.index + " ; următoarea căutare va începe de la " + pattern.lastIndex);

O altă metodă a obiectului RegExp este Test(), ceea ce este mult metoda mai simpla exec(). Ia un șir și returnează adevărat dacă șirul se potrivește cu expresia regulată:

Var model = /java/i; pattern.test("JavaScript"); // Returnează adevărat

Apelarea test() este echivalentă cu apelarea exec(), care returnează adevărat dacă exec() returnează altceva decât null. Din acest motiv, metoda test() se comportă în același mod ca metoda exec() atunci când este apelată pe o expresie regulată globală: începe căutarea șirului specificat la poziția specificată de proprietatea lastIndex și dacă găsește o potrivire , setează proprietatea lastIndex la numărul poziției caracterului direct lângă potrivirea găsită. Prin urmare, folosind metoda test(), puteți crea o buclă de traversare a liniilor în același mod ca și metoda exec().

Unii oameni, atunci când se confruntă cu o problemă, gândesc: „Oh, voi folosi expresii obișnuite”. Acum au două probleme.
Jamie Zawinski

Yuan-Ma a spus: „Este nevoie de multă forță pentru a tăia lemnul peste granulația lemnului. Este nevoie de mult cod pentru a programa în structura problemei.
Maestrul Yuan-Ma, „Cartea programării”

Instrumentele și tehnicile de programare supraviețuiesc și se răspândesc într-o manieră evolutivă haotică. Uneori nu cei frumoși și străluciți supraviețuiesc, ci pur și simplu cei care funcționează suficient de bine în domeniul lor - de exemplu, dacă sunt integrati într-o altă tehnologie de succes.

În acest capitol, vom discuta despre un astfel de instrument - expresiile regulate. Acesta este un mod de a descrie modele în datele șir. Ei creează un limbaj mic, de sine stătător, care este inclus în JavaScript și în multe alte limbi și instrumente.

Programele regulate sunt atât foarte ciudate, cât și extrem de utile. Sintaxa lor este criptică, iar interfața lor de programare JavaScript este greoaie. Dar este un instrument puternic pentru explorarea și manipularea șirurilor. Odată ce le înțelegi, vei deveni un programator mai eficient.

Crearea unei expresii regulate

Regular – tip de obiect. Poate fi creat apelând constructorul RegExp sau scriind șablonul dorit, înconjurat de bare oblice.

Var re1 = new RegExp("abc"); var re2 = /abc/;

Ambele expresii regulate reprezintă același model: caracterul „a” urmat de caracterul „b” urmat de caracterul „c”.

Dacă utilizați constructorul RegExp, modelul este scris ca sfoară obișnuită, deci se aplică toate regulile privind barele oblice inverse.

A doua intrare, în care modelul este între bare oblice, tratează diferit barele oblice inverse. În primul rând, deoarece modelul se termină cu o oblică înainte, trebuie să punem o bară oblică inversă înaintea barei oblice pe care dorim să o includem în modelul nostru. În plus, barele oblice inverse care nu fac parte din caractere speciale precum \n vor fi păstrate (mai degrabă decât ignorate ca în șiruri de caractere) și vor schimba semnificația modelului. Unele caractere, cum ar fi semnul de întrebare sau plus, au o semnificație specială în expresiile obișnuite și, dacă trebuie să găsiți un astfel de caracter, acesta trebuie să fie precedat și de o bară oblică inversă.

Var eighteenPlus = /eighteen\+/;

Pentru a ști ce caractere trebuie să fie precedate de o bară oblică, trebuie să înveți o listă cu toate caracterele speciale din expresiile regulate. Acest lucru nu este încă posibil, așa că atunci când aveți îndoieli, puneți o bară oblică inversă în fața oricărui caracter care nu este o literă, un număr sau un spațiu.

Se verifică potriviri

Obisnuitii au mai multe metode. Cel mai simplu este testul. Dacă îi treceți un șir, acesta va returna o valoare booleană care indică dacă șirul conține o apariție a modelului dat.

Console.log(/abc/.test("abcde")); // → true console.log(/abc/.test("abxde")); // → fals

O secvență obișnuită constând numai din caractere nespeciale este pur și simplu o secvență a acestor caractere. Dacă abc este oriunde în linia pe care o testăm (nu doar la început), testul va returna adevărat.

Caut un set de personaje

De asemenea, puteți afla dacă un șir conține abc folosind indexOf. Modelele obișnuite vă permit să mergeți mai departe și să creați modele mai complexe.

Să presupunem că trebuie să găsim orice număr. Când punem un set de caractere între paranteze drepte în expresia regulată, înseamnă că acea parte a expresiei se potrivește cu oricare dintre caracterele din paranteze.

Ambele expresii sunt în linii care conțin un număr.

Console.log(//.test(„în 1992”)); // → adevărat console.log(//.test(„în 1992”)); // → adevărat

Între paranteze drepte, o liniuță între două caractere este utilizată pentru a specifica un interval de caractere, în care secvența este specificată de codarea Unicode. Caracterele de la 0 la 9 sunt doar acolo pe rând (coduri de la 48 la 57), așa că le captează pe toate și se potrivește cu orice număr.

Mai multe grupuri de caractere au propriile lor abrevieri încorporate.

\d Orice număr
\w Caracter alfanumeric
\s caracter de spațiu alb (spațiu, tabulator, linie nouă etc.)
\D nu un număr
\W nu este un caracter alfanumeric
\S nu este un caracter alb
. orice caracter, cu excepția linie nouă

Astfel, puteți seta formatul de dată și oră ca 30/01/2003 15:20 cu următoarea expresie:

Var dateTime = /\d\d-\d\d-\d\d\d\d \d\d:\d\d/; console.log(dateTime.test("30-01-2003 15:20")); // → true console.log(dateTime.test("30-Jan-2003 15:20")); // → fals

Arată groaznic, nu-i așa? Există prea multe bare oblice inverse, ceea ce face modelul dificil de înțeles. Îl vom îmbunătăți puțin mai târziu.

Barele oblice inverse pot fi folosite și între paranteze drepte. De exemplu, [\d.] înseamnă orice număr sau punct. Observați că perioada din parantezele pătrate își pierde semnificația specială și devine pur și simplu o perioadă. Același lucru este valabil și pentru alte caractere speciale, cum ar fi +.

Puteți inversa un set de caractere - adică să spunem că trebuie să găsiți orice caracter, cu excepția celor care sunt în set - prin plasarea unui semn ^ imediat după paranteza pătrată de deschidere.

Var notBinary = /[^01]/; console.log(notBinary.test("1100100010100110")); // → false console.log(notBinary.test("1100100010200110")); // → adevărat

Repetarea părților șablonului

Știm cum să găsim un număr. Ce se întâmplă dacă trebuie să găsim întregul număr - o secvență de una sau mai multe cifre?

Dacă puneți semnul + după ceva în secvența obișnuită, aceasta va însemna că acest element poate fi repetat de mai multe ori. /\d+/ înseamnă una sau mai multe cifre.

Console.log(/"\d+"/.test(""123"")); // → adevărat console.log(/"\d+"/.test("""")); // → false console.log(/"\d*"/.test(""123"")); // → adevărat console.log(/"\d*"/.test("""")); // → adevărat

Asteriscul * are aproape aceeași semnificație, dar permite ca modelul să apară de zero ori. Dacă ceva este urmat de un asterisc, atunci nu împiedică niciodată modelul să se afle în linie - doar apare acolo de zero ori.

Un semn de întrebare face ca o parte a modelului să fie opțională, ceea ce înseamnă că poate apărea zero sau o dată. În exemplul următor, poate apărea caracterul u, dar modelul se potrivește chiar și atunci când nu apare.

Var vecin = /neighbou?r/; console.log(vecin.test(„vecin”); // → adevărat console.log(vecin.test(„vecin”); // → adevărat

Acoladele sunt folosite pentru a specifica de câte ori trebuie să apară un model. (4) după un element înseamnă că trebuie să apară de 4 ori în linie. De asemenea, puteți specifica un interval: (2,4) înseamnă că elementul trebuie să apară de cel puțin 2 și nu mai mult de 4 ori.

O altă versiune a formatului de dată și oră, în care zilele, lunile și orele de una sau două cifre sunt permise. Și este, de asemenea, puțin mai lizibil.

Var dateTime = /\d(1,2)-\d(1,2)-\d(4) \d(1,2):\d(2)/; console.log(dateTime.test("30-1-2003 8:45")); // → adevărat

Puteți folosi spații deschise omițând unul dintre numere. (,5,) înseamnă că modelul poate apărea de la zero la cinci ori, iar (5,) înseamnă de la cinci sau mai multe.

Gruparea subexpresiilor

Pentru a utiliza operatorii * sau + pe mai multe elemente simultan, puteți folosi paranteze. Partea expresiei regulate cuprinsă între paranteze este considerată un element din punctul de vedere al operatorilor.

Var cartoonCrying = /boo+(hoo+)+/i; console.log(cartoonCrying.test ("Boohoooohoohooo")); // → adevărat

Primul și al doilea plus se aplică numai celui de-al doilea O din boo și hoo. Al treilea + se referă la întregul grup (hoo+), găsind una sau mai multe astfel de secvențe.

Litera i de la sfârșitul expresiei face ca expresia regulată să nu țină seama de majuscule și minuscule - astfel încât B se potrivește cu b.

Meciuri și grupe

Metoda de testare este cea mai simplă metodă de verificare a expresiilor regulate. Vă spune doar dacă a fost găsită o potrivire sau nu. Obișnuiții au, de asemenea, o metodă exec, care va returna null dacă nu a fost găsit nimic și, în caz contrar, va returna un obiect cu informații despre potrivire.

Var potrivire = /\d+/.exec("unul doi 100"); console.log(potrivire); // → ["100"] console.log(match.index); // → 8

Obiectul returnat de exec are o proprietate index, care conține numărul caracterului de la care a avut loc potrivirea. În general, obiectul arată ca o matrice de șiruri, unde primul element este șirul care a fost verificat pentru o potrivire. În exemplul nostru, aceasta va fi succesiunea de numere pe care o căutam.

Șirurile au o metodă de potrivire care funcționează în același mod.

Console.log("unul doi 100".match(/\d+/)); // → ["100"]

Când o expresie obișnuită conține subexpresii grupate prin paranteze, textul care se potrivește cu aceste grupuri va apărea de asemenea în matrice. Primul element este întotdeauna o potrivire completă. A doua este partea care s-a potrivit cu primul grup (cel ale cărui paranteze au apărut mai întâi), apoi al doilea grup și așa mai departe.

Var quotedText = /"([^"]*)"/; console.log(quotedText.exec ("ea a spus "bună"")); // → [""bună ziua", "bună ziua"]

Când un grup nu este găsit deloc (de exemplu, dacă este urmat de un semn de întrebare), poziția sa în matrice este nedefinită. Dacă un grup se potrivește de mai multe ori, atunci numai ultimul meci va fi în matrice.

Console.log(/bad(ly)?/.exec(„rea”); // → [„prost”, nedefinit] console.log(/(\d)+/.exec(„123”)); // → ["123", "3"]

Grupurile sunt utile pentru a prelua părți de șiruri. Dacă nu vrem doar să verificăm dacă un șir are o dată, ci să îl extragem și să creăm un obiect reprezentând data, putem include secvențele de numere în paranteze și selectam data din rezultatul exec.

Dar mai întâi, o mică digresiune în care vom afla modul preferat de a stoca data și ora în JavaScript.

Tipul de dată

JavaScript are tip standard obiect pentru date - sau mai bine zis, momente în timp. Se numește Data. Dacă pur și simplu creați un obiect dată folosind new, veți obține data și ora curente.

Console.log(data noua()); // → Duminica 09 noiembrie 2014 00:07:57 GMT+0300 (CET)

De asemenea, puteți crea un obiect care conține un anumit timp

Console.log(new Date(2015, 9, 21)); // → Miercuri 21 octombrie 2015 00:00:00 GMT+0300 (CET) console.log(new Date(2009, 11, 9, 12, 59, 59, 999)); // → Miercuri 09 decembrie 2009 12:59:59 GMT+0300 (CET)

JavaScript folosește o convenție în care numerele lunii încep cu zero și numerele zilei cu unu. Acest lucru este stupid și ridicol. Atenție.

Ultimele patru argumente (ore, minute, secunde și milisecunde) sunt opționale și sunt setate la zero dacă lipsesc.

Marcajele de timp sunt stocate ca număr de milisecunde care au trecut de la începutul anului 1970. Pentru perioadele înainte de 1970, sunt folosite numere negative (acest lucru se datorează convenției de timp Unix care a fost creată în acea perioadă). Metoda getTime a obiectului data returnează acest număr. Este în mod natural mare.
console.log(new Date(2013, 11, 19).getTime()); // → 1387407600000 console.log(new Date(1387407600000)); // → Joi, 19 decembrie 2013 00:00:00 GMT+0100 (CET)

Dacă dați constructorului Date un argument, acesta este tratat ca acest număr de milisecunde. Puteți obține valoarea curentă în milisecunde creând un obiect Date și apelând metoda getTime sau apelând funcția Date.now.

Obiectul Date are metode getFullYear, getMonth, getDate, getHours, getMinutes și getSeconds pentru a prelua componentele sale. Există, de asemenea, o metodă getYear care returnează un cod de două cifre destul de inutil, cum ar fi 93 sau 14.

Prin includerea părților relevante ale șablonului în paranteze, putem crea un obiect dată direct din șir.

Funcția findDate(șir) ( var dateTime = /(\d(1,2))-(\d(1,2))-(\d(4))/; var potrivire = dateTime.exec(șir); return new Date(Număr(potrivire), Număr(potrivire) - 1, Număr(potrivire) ) console.log(findDate("30-1-2003")); // → Joi, 30 ianuarie 2003 00:00:00 GMT+0100 (CET)

Limite de cuvinte și linii

Din păcate, findDate va extrage la fel de fericit și data fără sens 00-1-3000 din șirul „100-1-30000”. Potrivirea poate avea loc oriunde în șir, deci în acest caz, pur și simplu va începe de la al doilea caracter și se va termina pe al doilea caracter.

Dacă trebuie să forțăm potrivirea să preia întregul șir, folosim etichetele ^ și $. ^ se potrivește cu începutul liniei, iar $ se potrivește cu sfârșitul. Prin urmare, /^\d+$/ se potrivește unui șir format din doar una sau mai multe cifre, /^!/ se potrivește unui șir care începe cu semn de exclamareși /x^/ nu se potrivește cu nicio linie (nu poate exista un x înainte de începutul liniei).

Dacă, pe de altă parte, vrem doar să ne asigurăm că data începe și se termină la granița unui cuvânt, folosim semnul \b. O limită a unui cuvânt poate fi începutul sau sfârșitul unei linii sau orice loc dintr-o linie unde există un caracter alfanumeric \w pe o parte și un caracter nealfanumeric pe cealaltă parte.

Console.log(/cat/.test(„concatenate”)); // → true console.log(/\bcat\b/.test(„concatenate”)); // → fals

Rețineți că eticheta de delimitare nu este un simbol. Este pur și simplu o constrângere, ceea ce înseamnă că o potrivire are loc numai dacă este îndeplinită o anumită condiție.

Șabloane cu alegere

Să presupunem că trebuie să aflați dacă textul conține nu doar un număr, ci un număr urmat de porc, vaca sau pui la singular sau plural.

Ar fi posibil să scrieți trei expresii regulate și să le verificați una câte una, dar există o modalitate mai bună. Simbol | denotă o alegere între modelele din stânga și din dreapta acestuia. Și putem spune următoarele:

Var animalCount = /\b\d+ (porc|vacă|pui)s?\b/; console.log(animalCount.test("15 porci"); // → true console.log(animalCount.test("15 pui de porc")); // → fals

Parantezele delimitează porțiunea modelului la care se aplică | și mulți astfel de operatori pot fi plasați unul după altul pentru a indica o alegere dintre mai mult de două opțiuni.

Motor de căutare

Expresiile regulate pot fi considerate diagrame de flux. Următoarea diagramă descrie un exemplu recent de animale.

O expresie se potrivește cu un șir dacă este posibil să găsiți o cale din partea stângă a diagramei la dreapta. Ne amintim poziția curentă în linie și de fiecare dată când trecem prin dreptunghi, verificăm dacă partea de linie imediat după poziția noastră în ea se potrivește cu conținutul dreptunghiului.

Aceasta înseamnă că verificarea unei potriviri a caracterului nostru obișnuit în șirul „cei 3 porci” atunci când parcurgeți diagrama de flux arată astfel:

La poziția 4 există o limită de cuvânt și trecem de primul dreptunghi
- incepand de la pozitia a 4-a gasim numarul si trecem prin al doilea dreptunghi
- la poziția 5, o cale se închide înapoi în fața celui de-al doilea dreptunghi, iar a doua merge mai departe către dreptunghi cu un spațiu. Avem un spațiu, nu un număr și alegem a doua cale.
- acum suntem pe pozitia 6, inceputul “porcilor”, si la tripla ramificare a potecilor. Nu există „vacă” sau „pui” în linie, dar există „porc”, așa că alegem această cale.
- în poziția 9 după bifurcația triplă, o cale ocolește „s” și merge la ultimul dreptunghi de limită a cuvântului, iar a doua trece prin „s”. Avem un „s”, așa că mergem acolo.
- la poziția 10 suntem la sfârșitul liniei și doar limita cuvântului se poate potrivi. Capătul liniei este considerat graniță și trecem prin ultimul dreptunghi. Și acum am găsit cu succes șablonul nostru.

Practic, modul în care funcționează expresiile regulate este că algoritmul începe la începutul șirului și încearcă să găsească o potrivire acolo. În cazul nostru, există o limită a cuvântului, deci trece de primul dreptunghi - dar nu există niciun număr acolo, așa că se împiedică de al doilea dreptunghi. Apoi trece la al doilea caracter din șir și încearcă să găsească o potrivire acolo... Și așa mai departe până când găsește o potrivire sau ajunge la sfârșitul șirului, caz în care nu se găsește nicio potrivire.

Kickback-uri

Expresia regulată /\b(+b|\d+|[\da-f]h)\b/ se potrivește fie cu un număr binar urmat de un b, cu un număr zecimal fără sufix, fie cu un număr hexazecimal (numerele de la 0 la 9 sau simbolurile de la a la h), urmate de h. Diagrama relevanta:

Când căutați o potrivire, se poate întâmpla ca algoritmul să ia calea de sus (număr binar), chiar dacă nu există un astfel de număr în șir. Dacă există o linie „103”, de exemplu, este clar că numai după ce ajunge la numărul 3 algoritmul va înțelege că este pe calea greșită. În general, linia se potrivește cu secvența obișnuită, doar că nu în acest fir.

Apoi algoritmul revine. La o bifurcație, își amintește poziția curentă (în cazul nostru, acesta este începutul liniei, imediat după limita cuvântului) astfel încât să poți să te întorci și să încerci o altă cale dacă cea aleasă nu funcționează. Pentru șirul „103”, după ce ați întâlnit un trei, se va întoarce și va încerca să treacă prin calea zecimală. Acest lucru va funcționa, astfel încât o potrivire va fi găsită.

Algoritmul se oprește imediat ce găsește o potrivire completă. Aceasta înseamnă că, chiar dacă mai multe opțiuni pot fi potrivite, se folosește doar una dintre ele (în ordinea în care apar în secvența obișnuită).

Backtracking apare atunci când se utilizează operatori de repetiție precum + și *. Dacă căutați /^.*x/ în șirul „abcxe”, partea regex.* va încerca să consume întregul șir. Algoritmul va realiza apoi că are nevoie și de „x”. Deoarece nu există niciun „x” după sfârșitul șirului, algoritmul va încerca să caute o potrivire deplasând înapoi cu un caracter. După abcx nu există nici un x, apoi se întoarce din nou, de data aceasta la subșirul abc. Iar după linie, găsește x și raportează o potrivire reușită, în pozițiile 0 la 4.

Puteți scrie o rutină obișnuită care va duce la mai multe derulări. Această problemă apare atunci când modelul poate potrivi datele de intrare de mai multe ori. căi diferite. De exemplu, dacă facem o greșeală când scriem o expresie regulată for numere binare, am putea scrie accidental ceva de genul /(+)+b/.

Dacă algoritmul ar căuta un astfel de model într-un șir lung de 0 și 1 care nu avea un „b” la sfârșit, ar trece mai întâi prin bucla interioară până când rămâne fără cifre. Apoi va observa că nu există „b” la sfârșit, va întoarce o poziție înapoi, va trece prin bucla exterioară, va renunța din nou, va încerca să se întoarcă înapoi în altă poziție de-a lungul buclei interioare... Și va continua pentru a căuta în acest fel, folosind ambele bucle. Adică, cantitatea de lucru cu fiecare caracter al liniei se va dubla. Chiar și pentru câteva zeci de personaje, găsirea unei potriviri va dura foarte mult timp.

metoda înlocuirii

Șirurile au o metodă de înlocuire care poate înlocui o parte dintr-un șir cu un alt șir.

Console.log("tata".replace("p", "m")); // → hartă

Primul argument poate fi și o expresie regulată, caz în care prima apariție a expresiei regulate din linie este înlocuită. Când opțiunea „g” (globală) este adăugată la expresia regulată, toate aparițiile sunt înlocuite, nu doar prima

Console.log("Borobudur".replace(//, "a")); // → Barobudur console.log("Borobudur".replace(//g, "a")); // → Barabadar

Ar fi logic să treceți opțiunea „înlocuiți tot” printr-un argument separat sau printr-o metodă separată, cum ar fi înlocuiți toate. Dar, din păcate, opțiunea este transmisă prin sistemul obișnuit în sine.

Puterea deplină a expresiilor regulate este dezvăluită atunci când folosim link-uri către grupuri găsite într-un șir, specificate în expresia regulată. De exemplu, avem o linie care conține numele persoanelor, câte un nume pe rând, în formatul „Nume, Prenume”. Dacă trebuie să le schimbăm și să eliminăm virgula pentru a obține „Nume de familie”, scriem următoarele:

Console.log(„Hopper, Grace\nMcCarthy, John\nRitchie, Dennis” .replace(/([\w ]+), ([\w ]+)/g, „$2 $1”); // → Grace Hopper // John McCarthy // Dennis Ritchie

$1 și $2 în linia de înlocuire se referă la grupuri de caractere cuprinse între paranteze. $1 este înlocuit cu textul care se potrivește cu primul grup, $2 cu al doilea grup și așa mai departe, până la $9. Întreaga potrivire este conținută în variabila $&.

De asemenea, puteți trece o funcție ca al doilea argument. Pentru fiecare înlocuire, va fi apelată o funcție ale cărei argumente vor fi grupurile găsite (și toată partea corespunzătoare a liniei), iar rezultatul acesteia va fi inserat într-o nouă linie.

Exemplu simplu:

Var s = „cia și fbi”; console.log(s.replace(/\b(fbi|cia)\b/g, function(str) ( return str.toUpperCase(); ))); // → CIA și FBI

Iată una mai interesantă:

Stock de var = „1 lămâie, 2 varze și 101 ouă”; funcția minusOne(potrivire, cantitate, unitate) ( cantitate = Număr (cantitate) - 1; dacă (cantitate == 1) // a rămas doar unul, eliminați „s” de la sfârșit unit = unit.slice(0, unit. lungime - 1; else if (cantitate == 0) suma = "nu" + unitate) console.log(stock.replace(/(\d+)/g, minusOne); ); // → fără lămâie, 1 varză și 100 de ouă

Codul ia un șir, găsește toate aparițiile numerelor urmate de un cuvânt și returnează un șir cu fiecare număr redus cu unul.

Grupul (\d+) intră în argumentul cantitate, iar (\w+) intră în argumentul unitate. Funcția convertește suma într-un număr - și aceasta funcționează întotdeauna, deoarece modelul nostru este \d+. Și apoi face modificări la cuvânt, în cazul în care rămâne doar 1 articol.

Lăcomie

Este ușor de utilizat înlocuire pentru a scrie o funcție care elimină toate comentariile din codul JavaScript. Iată prima încercare:

Funcția stripComments(cod) ( return code.replace(/\/\/.*|\/\*[^]*\*\//g, ""); ) console.log(stripComments("1 + /* 2 */3")); // → 1 + 3 console.log(stripComments("x = 10;// zece!")); // → x = 10; console.log(stripComments("1 /* a */+/* b */ 1")); // → 1 1

Partea dinaintea operatorului „sau” se potrivește cu două bare oblice urmate de orice număr de caractere, cu excepția liniilor noi. Partea care elimină comentariile pe mai multe rânduri este mai complexă. Folosim [^], i.e. orice caracter care nu este gol ca o modalitate de a găsi orice personaj. Nu putem folosi un punct deoarece blocarea comentariilor continuă linie nouă, iar caracterul newline nu se potrivește cu punctul.

Dar rezultatul exemplului anterior este incorect. De ce?

Partea [^]* va încerca mai întâi să captureze cât mai multe personaje. Dacă din această cauză următoarea parte a secvenței obișnuite nu găsește o potrivire, va derula un caracter înapoi și va încerca din nou. În exemplu, algoritmul încearcă să prindă întreaga linie, apoi se derulează înapoi. După ce a derulat înapoi 4 caractere, el va găsi */ în linie - și nu este ceea ce ne-am dorit. Am vrut să luăm un singur comentariu, și nu să mergem la sfârșitul rândului și să găsim ultimul comentariu.

Din această cauză, spunem că operatorii de repetiție (+, *, ? și ()) sunt lacomi, adică mai întâi apucă cât pot și apoi se întorc. Dacă puneți o întrebare după un astfel de operator (+?, *?, ??, ()?), ei se vor transforma în non-lacomi și vor începe să găsească cele mai mici apariții posibile.

Și de asta avem nevoie. Forțând asteriscul să găsească potriviri în numărul minim posibil de caractere dintr-o linie, consumăm doar un bloc de comentarii și nu mai mult.

Funcția stripComments(cod) ( return code.replace(/\/\/.*|\/\*[^]*?\*\//g, ""); ) console.log(stripComments("1 /* a */+/* b */ 1")); // → 1 + 1

Multe erori apar atunci când se folosesc operatori lacomi în loc de cei care nu sunt lacomi. Când utilizați operatorul de repetare, luați în considerare întotdeauna mai întâi operatorul non-lacom.

Crearea dinamică a obiectelor RegExp

În unele cazuri, modelul exact este necunoscut în momentul scrierii codului. De exemplu, va trebui să căutați numele utilizatorului în text și să-l încadrați în litere de subliniere. Deoarece veți ști numele numai după rularea programului, nu puteți utiliza notația oblică.

Dar puteți construi șirul și utilizați constructorul RegExp. Iată un exemplu:

Var nume = „harry”; var text = „Și Harry are o cicatrice pe frunte.”; var regexp = new RegExp("\\b(" + nume + ")\\b", "gi"); console.log(text.replace(regexp, "_$1_")); // → Și _Harry_ are o cicatrice pe frunte.

Când creăm limite de cuvinte, trebuie să folosim bare oblice duble pentru că le scriem într-o linie normală, și nu într-o secvență obișnuită cu bare oblice înainte. Al doilea argument la RegExp conține opțiuni pentru expresii regulate - în cazul nostru „gi”, adică. globală și fără majuscule.

Dar dacă numele este „dea+hlrd” (dacă utilizatorul nostru este un kulhatzker)? Ca rezultat, vom obține o expresie regulată fără sens care nu va găsi potriviri în șir.

Putem adăuga bare oblice inverse înaintea oricărui personaj care nu ne place. Nu putem adăuga bare oblice inverse înainte de litere deoarece \b sau \n sunt caractere speciale. Dar puteți adăuga bare oblice înaintea oricăror caractere non-alfanumerice fără probleme.

Var name = "dea+hlrd"; var text = "Acest dea+hlrd enervează pe toată lumea."; var escape = name.replace(/[^\w\s]/g, "\\$&"); var regexp = new RegExp("\\b(" + escape + ")\\b", "gi"); console.log(text.replace(regexp, "_$1_")); // → Această _dea+hlrd_ a enervat pe toată lumea.

metoda de cautare

Metoda indexOf nu poate fi utilizată cu expresii regulate. Dar există o metodă de căutare care așteaptă doar expresia regulată. La fel ca indexOf, returnează indexul primei apariții sau -1 dacă nu apare niciuna.

Console.log("cuvânt".search(/\S/)); // → 2 console.log(" ".search(/\S/)); // → -1

Din păcate, nu există nicio modalitate de a spune metodei să caute o potrivire începând cu un anumit offset (cum poți face cu indexOf). Asta ar fi de ajutor.

proprietate lastIndex

Nici metoda exec nu funcționează mod convenabilîncepeți căutarea dintr-o poziție dată în șir. Dar oferă un mod incomod.

Un obiect regex are proprietăți. Una dintre ele este sursa, care conține un șir. Un altul este lastIndex, care controlează, în anumite condiții, unde va începe următoarea căutare a aparițiilor.

Aceste condiții includ faptul că opțiunea globală g trebuie să fie prezentă și că căutarea trebuie făcută folosind metoda exec. Mai mult decizie rezonabilă Ar fi simplu să permiteți ca un argument suplimentar să fie transmis către exec, dar inteligența nu este o caracteristică fundamentală a interfeței JavaScript regex.

Var model = /y/g; pattern.lastIndex = 3; var potrivire = pattern.exec("xyzzy"); console.log(match.index); // → 4 console.log(pattern.lastIndex); // → 5

Dacă căutarea a avut succes, apelul exec actualizează proprietatea lastIndex pentru a indica poziția după apariția găsită. Dacă nu a avut succes, lastIndex este setat la zero - la fel ca lastIndex al obiectului nou creat.

Când utilizați o variabilă obișnuită globală și apeluri multiple de exec, aceste actualizări automate lastIndex pot cauza probleme. Serverul dvs. obișnuit poate începe să caute din poziția rămasă de la apelul anterior.

Var digit = /\d/g; console.log(digit.exec ("aici este: 1")); // → ["1"] console.log(digit.exec("și acum: 1")); // → nul

O alta efect interesant Opțiunea g este că schimbă modul în care funcționează metoda de potrivire. Când este apelat cu această opțiune, în loc să returneze o matrice similară cu rezultatul exec, găsește toate aparițiile modelului din șir și returnează o matrice a subșirurilor găsite.

Console.log("Banana".match(/an/g)); // → ["un", "un"]

Așa că aveți grijă cu variabilele globale regulate. Cazurile în care sunt necesare - înlocuiți apelurile sau locurile în care utilizați în mod specific lastIndex - sunt probabil toate cazurile în care ar trebui să fie utilizate.

Cicluri de apariție

O sarcină tipică este să iterați prin toate aparițiile unui model dintr-un șir, astfel încât să poată accesa obiectul potrivire din corpul buclei folosind lastIndex și exec.

Var input = "O linie cu 3 numere în ea... 42 și 88."; număr var = /\b(\d+)\b/g; var potrivire; while (potrivire = număr.exec(input)) console.log(„Găsit”, potrivire, „pe”, potrivire.index); // → Găsit 3 la 14 // Găsit 42 la 33 // Găsit 88 la 40

Profită de faptul că valoarea atribuirii este valoarea atribuită. Folosind match = re.exec(input) ca o condiție într-o buclă while, căutăm la începutul fiecărei iterații, stocăm rezultatul într-o variabilă și încheiem bucla când sunt găsite toate potrivirile.

Analizarea fișierelor INI

Pentru a încheia capitolul, să ne uităm la o problemă folosind expresii regulate. Imaginați-vă că scriem un program care colectează automat informații despre inamicii noștri prin Internet. (Nu vom scrie întregul program, ci doar partea care citește fișierul de setări. Ne pare rău.) Fișierul arată astfel:

Searchengine=http://www.google.com/search?q=$1 spitefulness=9.7 ; înaintea comentariilor se pune punct și virgulă; fiecare secțiune se referă la un inamic diferit nume complet=Larry Doe tip=website de taur de grădiniță=http://www.geocities.com/CapeCanaveral/11451 fullname=Gargamel type=evil wizard outputdir=/home/marijn/enemies/gargamel

Formatul exact de fișier (care este destul de utilizat pe scară largă și se numește de obicei INI) este următorul:

Liniile goale și liniile care încep cu punct și virgulă sunt ignorate
- liniile cuprinse între paranteze drepte încep o nouă secțiune
- linii care conțin un identificator alfanumeric urmat de = adăugați o setare în această secțiune

Toate celelalte sunt date incorecte.

Sarcina noastră este să convertim un astfel de șir într-o matrice de obiecte, fiecare cu o proprietate de nume și o matrice de setări. Este necesar un obiect pentru fiecare secțiune, iar altul este necesar pentru setările globale din partea de sus a fișierului.

Deoarece fișierul trebuie analizat linie cu linie, este o idee bună să începeți prin a împărți fișierul în linii. Pentru a face acest lucru, am folosit string.split("\n") în Capitolul 6. Unele sisteme de operare folosesc nu un caracter \n pentru întreruperi de linie, ci două - \r\n. Deoarece metoda split ia ca argument expresiile regulate, putem împărți linii folosind expresia /\r?\n/, permițând atât \n cât și \r\n între linii.

Funcția parseINI(șir) ( // Să începem cu un obiect care conține setări nivel superior var currentSection = (nume: null, câmpuri: ); var categorii = ; string.split(/\r?\n/).forEach(function(line) ( var potrivire; if (/^\s*(;.*)?$/.test(line)) ( return; ) else if (potrivire = line.match(/^\[(.*)\]$/)) ( currentSection = (nume: potrivire, câmpuri: ); categories.push(currentSection); ) else if (potrivire = line.match( /^(\w+)=(.*)$/)) ( currentSection.fields.push((nume: potrivire, valoare: potrivire)); ) else ( throw new Error ("Linia "" + linia + "" conține date greșite."); ) )); categorii de returnare; )

Codul parcurge toate liniile, actualizând obiectul secțiunii curente „secțiunea curentă”. În primul rând, verifică dacă linia poate fi ignorată folosind expresia regulată /^\s*(;.*)?$/. Vă puteți imagina cum funcționează asta? Partea dintre paranteze se potrivește cu comentariile, nu? face astfel încât caracterul obișnuit să se potrivească, de asemenea, linii formate doar din spații.

Dacă linia nu este un comentariu, codul verifică dacă începe o nouă secțiune. Dacă da, creează un nou obiect pentru secțiunea curentă, la care se adaugă setările ulterioare.

Ultima posibilitate semnificativă este ca șirul să fie o setare normală, caz în care este adăugat obiectului curent.

Dacă niciuna dintre opțiuni nu funcționează, funcția afișează o eroare.

Observați cum utilizarea frecventă a ^ și $ asigură că expresia se potrivește întregului șir, mai degrabă decât doar o parte a acestuia. Dacă nu le folosiți, codul va funcționa în general, dar uneori va produce rezultate ciudate și eroarea va fi dificil de găsit.

Construcția if (match = string.match(...)) este similară cu trucul de a folosi atribuirea ca condiție într-o buclă while. Adesea nu știi că apelul de potrivire va reuși, așa că poți accesa doar obiectul rezultat în interiorul unui bloc if care îl verifică. Pentru a nu rupe lanțul frumos al verificărilor if, atribuim rezultatul căutării unei variabile și folosim imediat această atribuire ca verificare.

Simboluri internaționale

Datorită implementării inițial simple a limbajului și fixării ulterioare a unei astfel de implementări „în granit”, expresiile regulate JavaScript sunt stupide cu caractere care nu se găsesc în limba engleză. De exemplu, caracterul „litera”, din punctul de vedere al expresiilor regulate JavaScript, poate fi una dintre cele 26 de litere ale alfabetului englez și, din anumite motive, și un caracter de subliniere. Litere precum é sau β, care sunt în mod clar litere, nu se potrivesc cu \w (și se vor potrivi cu \W, care este o non-litera).

Într-o întorsătură ciudată, din punct de vedere istoric, \s (spațiu) se potrivește cu toate caracterele care sunt considerate spații albe în Unicode, inclusiv lucruri precum spațiul care nu se întrerupe sau separatorul de vocale mongole.

Unele implementări regex în alte limbi au sintaxă specială pentru căutarea categoriilor speciale de caractere Unicode, cum ar fi „toate litere mari”, „toate semnele de punctuație” sau „caracterele de control”. Există planuri de a adăuga astfel de categorii la JavaScript, dar probabil că acestea nu vor fi implementate în curând.

Concluzie

Regularii sunt obiecte care reprezintă modele de căutare în șiruri. Ei folosesc propria sintaxă pentru a exprima aceste modele.

/abc/ Secvență de caractere
// Orice caracter din listă
/[^abc]/ Orice caracter, cu excepția caracterelor din listă
// Orice caracter din interval
/x+/ Una sau mai multe apariții ale modelului x
/x+?/ Una sau mai multe apariții, nelacom
/x*/ Zero sau mai multe apariții
/x?/ Zero sau o apariție
/x(2,4)/ De la două până la patru apariții
/(abc)/ Grup
/a|b|c/ Oricare dintre mai multe modele
/\d/ Orice număr
/\w/ Orice caracter alfanumeric („litera”)
/\s/ Orice caracter alb
/./ Orice caracter, cu excepția liniilor noi
/\b/ Limita cuvântului
/^/ Începutul liniei
/$/ Sfârșitul rândului

Regex are o metodă de testare pentru a verifica dacă modelul este în șir. Există o metodă exec care returnează o matrice care conține toate grupurile găsite. Matricea are o proprietate index, care conține numărul caracterului de la care a avut loc potrivirea.

Șirurile au o metodă de potrivire pentru a potrivi modelele și o metodă de căutare care returnează doar poziția de pornire a apariției. Metoda de înlocuire poate înlocui aparițiile unui model cu un alt șir. În plus, puteți trece o funcție de înlocuit care va construi o linie de înlocuire pe baza șablonului și a grupurilor găsite.

Caracterele obișnuite au setări care sunt scrise după bara oblică de închidere. Opțiunea i face ca expresia regulată să nu țină seama de majuscule și minuscule, iar opțiunea g o face globală, ceea ce, printre altele, face ca metoda de înlocuire să înlocuiască toate aparițiile găsite, nu doar prima.

Constructorul RegExp poate fi folosit pentru a crea expresii regulate din șiruri.

Regulatoarele sunt un instrument ascuțit cu un mâner inconfortabil. Ele simplifică foarte mult unele sarcini și pot deveni de negestionat atunci când rezolvăm alte probleme complexe. O parte a învățării să folosești regexe este să poți rezista tentației de a le umple cu o sarcină pentru care nu sunt destinate.

Exerciții

Inevitabil, atunci când rezolvi probleme, vei întâlni cazuri de neînțeles, iar uneori s-ar putea să disperi când vezi comportamentul imprevizibil al unor expresii regulate. Uneori ajută să studiezi comportamentul unui motor obișnuit printr-un serviciu online precum debuggex.com, unde poți vedea vizualizarea acestuia și îl poți compara cu efectul dorit.
Golf obișnuit
„Golf” în cod este un joc în care trebuie să te exprimi programul dat număr minim de caractere. Golful obișnuit este un exercițiu practic de a scrie cei mai mici obișnuiți posibil pentru a găsi un model dat și doar atât.

Pentru fiecare dintre sublinii, scrieți o expresie regulată pentru a verifica locația lor în linie. Motorul obișnuit ar trebui să găsească numai aceste subșiruri specificate. Nu vă faceți griji cu privire la limitele cuvintelor decât dacă sunt menționate în mod specific. Când aveți un model obișnuit de lucru, încercați să îl reduceți.

Mașină și pisică
- pop și prop
- dihor, feribot și ferrari
- Orice cuvânt care se termină în ious
- Un spațiu urmat de un punct, virgulă, două puncte sau punct și virgulă.
- Un cuvânt mai lung de șase litere
- Cuvânt fără litere e

// Introduceți expresiile regulate verify(/.../, ["mașina mea", "pisicile rele"], ["camper", "high art"]); verifică(/.../, ["cultură pop", "recuzită nebună"], ["plop"]); verifica(/.../, ["dihor", "feribot", "ferrari"], ["ferrum", "transfer A"]); verifica(/.../, [„cât de delicios”, „cameră spațioasă”], [„ruinator”, „conștiință”]); verifică(/.../, ["punctuație proastă."], ["escape the dot"]); verifică(/.../, ["hottenottententen"], ["nu", "hotten totten tenten"]); verifică(/.../, [„ornitorinc roșu”, „cuib clătinat”], [„pat de pământ”, „maimuță care învață”]); function verify(regexp, yes, no) ( // Ignora exercitiile neterminate daca (regexp.source == "...") return; yes.forEach(function(s) ( if (!regexp.test(s))) consola .log("Nu a fost găsită "" + s + """ )); ); ));

Citate în text
Să presupunem că ai scris o poveste și peste tot ai indicat dialoguri ghilimele simple. Acum doriți să înlocuiți ghilimelele de dialog cu ghilimele duble și să lăsați ghilimele simple în abrevieri ale cuvintelor precum aren’t.

Veniți cu un model care să facă distincția între aceste două utilizări ale ghilimelelor și scrieți un apel la metoda înlocuire care face înlocuirea.

Din nou numere
Secvențele de numere pot fi găsite cu o expresie regulată simplă /\d+/.

Scrieți o expresie care găsește numai numere scrise în stil JavaScript. Trebuie să suporte un posibil minus sau plus înaintea numărului, un punct zecimal și notația științifică 5e-3 sau 1E10 - din nou cu un posibil plus sau minus. De asemenea, rețineți că este posibil să nu existe neapărat numere înainte sau după punct, dar numărul nu poate consta dintr-un singur punct. Adică, .5 sau 5. sunt numere valide, dar un punct în sine nu este.

// Introduceți secvența obișnuită aici. var număr = /^...$/; // Teste: ["1", "-1", "+15", "1.55", ".5", "5.", "1.3e2", "1E-4", "1e+12"] .forEach(funcție(i) ( dacă (!număr.test(e)) console.log("Nu am găsit "" + s + """); )); ["1a", "+-1", "1.2.3", "1+1", "1e4.5", ".5.", "1f5", "."].forEach(funcție(i) ( if (număr.test(e)) console.log("Acceptat incorect "" + s + """); ));

Unii oameni, atunci când se confruntă cu o problemă, gândesc: „Oh, voi folosi expresii obișnuite”. Acum au două probleme.
Jamie Zawinski

Yuan-Ma a spus: „Este nevoie de multă forță pentru a tăia lemnul peste granulația lemnului. Este nevoie de mult cod pentru a programa în structura problemei.
Maestrul Yuan-Ma, „Cartea programării”

Instrumentele și tehnicile de programare supraviețuiesc și se răspândesc într-o manieră evolutivă haotică. Uneori nu cei frumoși și străluciți supraviețuiesc, ci pur și simplu cei care funcționează suficient de bine în domeniul lor - de exemplu, dacă sunt integrati într-o altă tehnologie de succes.

În acest capitol, vom discuta despre un astfel de instrument - expresiile regulate. Acesta este un mod de a descrie modele în datele șir. Ei creează un limbaj mic, de sine stătător, care este inclus în JavaScript și în multe alte limbi și instrumente.

Programele regulate sunt atât foarte ciudate, cât și extrem de utile. Sintaxa lor este criptică, iar interfața lor de programare JavaScript este greoaie. Dar este un instrument puternic pentru explorarea și manipularea șirurilor. Odată ce le înțelegi, vei deveni un programator mai eficient.

Crearea unei expresii regulate

Regular – tip de obiect. Poate fi creat apelând constructorul RegExp sau scriind șablonul dorit, înconjurat de bare oblice.

Var re1 = new RegExp("abc"); var re2 = /abc/;

Ambele expresii regulate reprezintă același model: caracterul „a” urmat de caracterul „b” urmat de caracterul „c”.

Dacă utilizați constructorul RegExp, atunci modelul este scris ca un șir obișnuit, deci se aplică toate regulile privind barele oblice inverse.

A doua intrare, în care modelul este între bare oblice, tratează diferit barele oblice inverse. În primul rând, deoarece modelul se termină cu o oblică înainte, trebuie să punem o bară oblică inversă înaintea barei oblice pe care dorim să o includem în modelul nostru. În plus, barele oblice inverse care nu fac parte din caractere speciale precum \n vor fi păstrate (mai degrabă decât ignorate ca în șiruri de caractere) și vor schimba semnificația modelului. Unele caractere, cum ar fi semnul de întrebare sau plus, au o semnificație specială în expresiile obișnuite și, dacă trebuie să găsiți un astfel de caracter, acesta trebuie să fie precedat și de o bară oblică inversă.

Var eighteenPlus = /eighteen\+/;

Pentru a ști ce caractere trebuie să fie precedate de o bară oblică, trebuie să înveți o listă cu toate caracterele speciale din expresiile regulate. Acest lucru nu este încă posibil, așa că atunci când aveți îndoieli, puneți o bară oblică inversă în fața oricărui caracter care nu este o literă, un număr sau un spațiu.

Se verifică potriviri

Obisnuitii au mai multe metode. Cel mai simplu este testul. Dacă îi treceți un șir, acesta va returna o valoare booleană care indică dacă șirul conține o apariție a modelului dat.

Console.log(/abc/.test("abcde")); // → true console.log(/abc/.test("abxde")); // → fals

O secvență obișnuită constând numai din caractere nespeciale este pur și simplu o secvență a acestor caractere. Dacă abc este oriunde în linia pe care o testăm (nu doar la început), testul va returna adevărat.

Caut un set de personaje

De asemenea, puteți afla dacă un șir conține abc folosind indexOf. Modelele obișnuite vă permit să mergeți mai departe și să creați modele mai complexe.

Să presupunem că trebuie să găsim orice număr. Când punem un set de caractere între paranteze drepte în expresia regulată, înseamnă că acea parte a expresiei se potrivește cu oricare dintre caracterele din paranteze.

Ambele expresii sunt în linii care conțin un număr.

Console.log(//.test(„în 1992”)); // → adevărat console.log(//.test(„în 1992”)); // → adevărat

Între paranteze drepte, o liniuță între două caractere este utilizată pentru a specifica un interval de caractere, în care secvența este specificată de codarea Unicode. Caracterele de la 0 la 9 sunt doar acolo pe rând (coduri de la 48 la 57), așa că le captează pe toate și se potrivește cu orice număr.

Mai multe grupuri de caractere au propriile lor abrevieri încorporate.

\d Orice număr
\w Caracter alfanumeric
\s caracter de spațiu alb (spațiu, tabulator, linie nouă etc.)
\D nu un număr
\W nu este un caracter alfanumeric
\S nu este un caracter alb
. orice caracter, cu excepția linie nouă

Astfel, puteți seta formatul de dată și oră ca 30/01/2003 15:20 cu următoarea expresie:

Var dateTime = /\d\d-\d\d-\d\d\d\d \d\d:\d\d/; console.log(dateTime.test("30-01-2003 15:20")); // → true console.log(dateTime.test("30-Jan-2003 15:20")); // → fals

Arată groaznic, nu-i așa? Există prea multe bare oblice inverse, ceea ce face modelul dificil de înțeles. Îl vom îmbunătăți puțin mai târziu.

Barele oblice inverse pot fi folosite și între paranteze drepte. De exemplu, [\d.] înseamnă orice număr sau punct. Observați că perioada din parantezele pătrate își pierde semnificația specială și devine pur și simplu o perioadă. Același lucru este valabil și pentru alte caractere speciale, cum ar fi +.

Puteți inversa un set de caractere - adică să spunem că trebuie să găsiți orice caracter, cu excepția celor care sunt în set - prin plasarea unui semn ^ imediat după paranteza pătrată de deschidere.

Var notBinary = /[^01]/; console.log(notBinary.test("1100100010100110")); // → false console.log(notBinary.test("1100100010200110")); // → adevărat

Repetarea părților șablonului

Știm cum să găsim un număr. Ce se întâmplă dacă trebuie să găsim întregul număr - o secvență de una sau mai multe cifre?

Dacă puneți semnul + după ceva în secvența obișnuită, aceasta va însemna că acest element poate fi repetat de mai multe ori. /\d+/ înseamnă una sau mai multe cifre.

Console.log(/"\d+"/.test(""123"")); // → adevărat console.log(/"\d+"/.test("""")); // → false console.log(/"\d*"/.test(""123"")); // → adevărat console.log(/"\d*"/.test("""")); // → adevărat

Asteriscul * are aproape aceeași semnificație, dar permite ca modelul să apară de zero ori. Dacă ceva este urmat de un asterisc, atunci nu împiedică niciodată modelul să se afle în linie - doar apare acolo de zero ori.

Un semn de întrebare face ca o parte a modelului să fie opțională, ceea ce înseamnă că poate apărea zero sau o dată. În exemplul următor, poate apărea caracterul u, dar modelul se potrivește chiar și atunci când nu apare.

Var vecin = /neighbou?r/; console.log(vecin.test(„vecin”); // → adevărat console.log(vecin.test(„vecin”); // → adevărat

Acoladele sunt folosite pentru a specifica de câte ori trebuie să apară un model. (4) după un element înseamnă că trebuie să apară de 4 ori în linie. De asemenea, puteți specifica un interval: (2,4) înseamnă că elementul trebuie să apară de cel puțin 2 și nu mai mult de 4 ori.

O altă versiune a formatului de dată și oră, în care zilele, lunile și orele de una sau două cifre sunt permise. Și este, de asemenea, puțin mai lizibil.

Var dateTime = /\d(1,2)-\d(1,2)-\d(4) \d(1,2):\d(2)/; console.log(dateTime.test("30-1-2003 8:45")); // → adevărat

Puteți folosi spații deschise omițând unul dintre numere. (,5,) înseamnă că modelul poate apărea de la zero la cinci ori, iar (5,) înseamnă de la cinci sau mai multe.

Gruparea subexpresiilor

Pentru a utiliza operatorii * sau + pe mai multe elemente simultan, puteți folosi paranteze. Partea expresiei regulate cuprinsă între paranteze este considerată un element din punctul de vedere al operatorilor.

Var cartoonCrying = /boo+(hoo+)+/i; console.log(cartoonCrying.test ("Boohoooohoohooo")); // → adevărat

Primul și al doilea plus se aplică numai celui de-al doilea O din boo și hoo. Al treilea + se referă la întregul grup (hoo+), găsind una sau mai multe astfel de secvențe.

Litera i de la sfârșitul expresiei face ca expresia regulată să nu țină seama de majuscule și minuscule - astfel încât B se potrivește cu b.

Meciuri și grupe

Metoda de testare este cea mai simplă metodă de verificare a expresiilor regulate. Vă spune doar dacă a fost găsită o potrivire sau nu. Obișnuiții au, de asemenea, o metodă exec, care va returna null dacă nu a fost găsit nimic și, în caz contrar, va returna un obiect cu informații despre potrivire.

Var potrivire = /\d+/.exec("unul doi 100"); console.log(potrivire); // → ["100"] console.log(match.index); // → 8

Obiectul returnat de exec are o proprietate index, care conține numărul caracterului de la care a avut loc potrivirea. În general, obiectul arată ca o matrice de șiruri, unde primul element este șirul care a fost verificat pentru o potrivire. În exemplul nostru, aceasta va fi succesiunea de numere pe care o căutam.

Șirurile au o metodă de potrivire care funcționează în același mod.

Console.log("unul doi 100".match(/\d+/)); // → ["100"]

Când o expresie obișnuită conține subexpresii grupate prin paranteze, textul care se potrivește cu aceste grupuri va apărea de asemenea în matrice. Primul element este întotdeauna o potrivire completă. A doua este partea care s-a potrivit cu primul grup (cel ale cărui paranteze au apărut mai întâi), apoi al doilea grup și așa mai departe.

Var quotedText = /"([^"]*)"/; console.log(quotedText.exec ("ea a spus "bună"")); // → [""bună ziua", "bună ziua"]

Când un grup nu este găsit deloc (de exemplu, dacă este urmat de un semn de întrebare), poziția sa în matrice este nedefinită. Dacă un grup se potrivește de mai multe ori, atunci numai ultimul meci va fi în matrice.

Console.log(/bad(ly)?/.exec(„rea”); // → [„prost”, nedefinit] console.log(/(\d)+/.exec(„123”)); // → ["123", "3"]

Grupurile sunt utile pentru a prelua părți de șiruri. Dacă nu vrem doar să verificăm dacă un șir are o dată, ci să îl extragem și să creăm un obiect reprezentând data, putem include secvențele de numere în paranteze și selectam data din rezultatul exec.

Dar mai întâi, o mică digresiune în care vom afla modul preferat de a stoca data și ora în JavaScript.

Tipul de dată

JavaScript are un tip de obiect standard pentru date – mai precis, momente în timp. Se numește Data. Dacă pur și simplu creați un obiect dată folosind new, veți obține data și ora curente.

Console.log(data noua()); // → Duminica 09 noiembrie 2014 00:07:57 GMT+0300 (CET)

De asemenea, puteți crea un obiect care conține un anumit timp

Console.log(new Date(2015, 9, 21)); // → Miercuri 21 octombrie 2015 00:00:00 GMT+0300 (CET) console.log(new Date(2009, 11, 9, 12, 59, 59, 999)); // → Miercuri 09 decembrie 2009 12:59:59 GMT+0300 (CET)

JavaScript folosește o convenție în care numerele lunii încep cu zero și numerele zilei cu unu. Acest lucru este stupid și ridicol. Atenție.

Ultimele patru argumente (ore, minute, secunde și milisecunde) sunt opționale și sunt setate la zero dacă lipsesc.

Marcajele de timp sunt stocate ca număr de milisecunde care au trecut de la începutul anului 1970. Pentru perioadele înainte de 1970, sunt folosite numere negative (acest lucru se datorează convenției de timp Unix care a fost creată în acea perioadă). Metoda getTime a obiectului data returnează acest număr. Este în mod natural mare.
console.log(new Date(2013, 11, 19).getTime()); // → 1387407600000 console.log(new Date(1387407600000)); // → Joi, 19 decembrie 2013 00:00:00 GMT+0100 (CET)

Dacă dați constructorului Date un argument, acesta este tratat ca acest număr de milisecunde. Puteți obține valoarea curentă în milisecunde creând un obiect Date și apelând metoda getTime sau apelând funcția Date.now.

Obiectul Date are metode getFullYear, getMonth, getDate, getHours, getMinutes și getSeconds pentru a prelua componentele sale. Există, de asemenea, o metodă getYear care returnează un cod de două cifre destul de inutil, cum ar fi 93 sau 14.

Prin includerea părților relevante ale șablonului în paranteze, putem crea un obiect dată direct din șir.

Funcția findDate(șir) ( var dateTime = /(\d(1,2))-(\d(1,2))-(\d(4))/; var potrivire = dateTime.exec(șir); return new Date(Număr(potrivire), Număr(potrivire) - 1, Număr(potrivire) ) console.log(findDate("30-1-2003")); // → Joi, 30 ianuarie 2003 00:00:00 GMT+0100 (CET)

Limite de cuvinte și linii

Din păcate, findDate va extrage la fel de fericit și data fără sens 00-1-3000 din șirul „100-1-30000”. Potrivirea se poate întâmpla oriunde în șir, așa că în acest caz va începe pur și simplu la al doilea caracter și se va termina la penulul caracter.

Dacă trebuie să forțăm potrivirea să preia întregul șir, folosim etichetele ^ și $. ^ se potrivește cu începutul liniei, iar $ se potrivește cu sfârșitul. Prin urmare, /^\d+$/ se potrivește unui șir care conține doar una sau mai multe cifre, /^!/ se potrivește unui șir care începe cu un semn de exclamare și /x^/ nu se potrivește cu niciun șir (nu poate exista un x).

Dacă, pe de altă parte, vrem doar să ne asigurăm că data începe și se termină la granița unui cuvânt, folosim semnul \b. O limită a unui cuvânt poate fi începutul sau sfârșitul unei linii sau orice loc dintr-o linie unde există un caracter alfanumeric \w pe o parte și un caracter nealfanumeric pe cealaltă parte.

Console.log(/cat/.test(„concatenate”)); // → true console.log(/\bcat\b/.test(„concatenate”)); // → fals

Rețineți că eticheta de delimitare nu este un simbol. Este pur și simplu o constrângere, ceea ce înseamnă că o potrivire are loc numai dacă este îndeplinită o anumită condiție.

Șabloane cu alegere

Să presupunem că trebuie să aflați dacă textul conține nu doar un număr, ci un număr urmat de porc, vaca sau pui la singular sau plural.

Ar fi posibil să scrieți trei expresii regulate și să le verificați una câte una, dar există o modalitate mai bună. Simbol | denotă o alegere între modelele din stânga și din dreapta acestuia. Și putem spune următoarele:

Var animalCount = /\b\d+ (porc|vacă|pui)s?\b/; console.log(animalCount.test("15 porci"); // → true console.log(animalCount.test("15 pui de porc")); // → fals

Parantezele delimitează porțiunea modelului la care se aplică | și mulți astfel de operatori pot fi plasați unul după altul pentru a indica o alegere dintre mai mult de două opțiuni.

Motor de căutare

Expresiile regulate pot fi considerate diagrame de flux. Următoarea diagramă descrie un exemplu recent de animale.

O expresie se potrivește cu un șir dacă este posibil să găsiți o cale din partea stângă a diagramei la dreapta. Ne amintim poziția curentă în linie și de fiecare dată când trecem prin dreptunghi, verificăm dacă partea de linie imediat după poziția noastră în ea se potrivește cu conținutul dreptunghiului.

Aceasta înseamnă că verificarea unei potriviri a caracterului nostru obișnuit în șirul „cei 3 porci” atunci când parcurgeți diagrama de flux arată astfel:

La poziția 4 există o limită de cuvânt și trecem de primul dreptunghi
- incepand de la pozitia a 4-a gasim numarul si trecem prin al doilea dreptunghi
- la poziția 5, o cale se închide înapoi în fața celui de-al doilea dreptunghi, iar a doua merge mai departe către dreptunghi cu un spațiu. Avem un spațiu, nu un număr și alegem a doua cale.
- acum suntem pe pozitia 6, inceputul “porcilor”, si la tripla ramificare a potecilor. Nu există „vacă” sau „pui” în linie, dar există „porc”, așa că alegem această cale.
- în poziția 9 după bifurcația triplă, o cale ocolește „s” și merge la ultimul dreptunghi de limită a cuvântului, iar a doua trece prin „s”. Avem un „s”, așa că mergem acolo.
- la poziția 10 suntem la sfârșitul liniei și doar limita cuvântului se poate potrivi. Capătul liniei este considerat graniță și trecem prin ultimul dreptunghi. Și acum am găsit cu succes șablonul nostru.

Practic, modul în care funcționează expresiile regulate este că algoritmul începe la începutul șirului și încearcă să găsească o potrivire acolo. În cazul nostru, există o limită a cuvântului, deci trece de primul dreptunghi - dar nu există niciun număr acolo, așa că se împiedică de al doilea dreptunghi. Apoi trece la al doilea caracter din șir și încearcă să găsească o potrivire acolo... Și așa mai departe până când găsește o potrivire sau ajunge la sfârșitul șirului, caz în care nu se găsește nicio potrivire.

Kickback-uri

Expresia regulată /\b(+b|\d+|[\da-f]h)\b/ se potrivește fie cu un număr binar urmat de un b, cu un număr zecimal fără sufix, fie cu un număr hexazecimal (numerele de la 0 la 9 sau simbolurile de la a la h), urmate de h. Diagrama relevanta:

Când căutați o potrivire, se poate întâmpla ca algoritmul să ia calea de sus (număr binar), chiar dacă nu există un astfel de număr în șir. Dacă există o linie „103”, de exemplu, este clar că numai după ce ajunge la numărul 3 algoritmul va înțelege că este pe calea greșită. În general, linia se potrivește cu secvența obișnuită, doar că nu în acest fir.

Apoi algoritmul revine. La o bifurcație, își amintește poziția curentă (în cazul nostru, acesta este începutul liniei, imediat după limita cuvântului) astfel încât să poți să te întorci și să încerci o altă cale dacă cea aleasă nu funcționează. Pentru șirul „103”, după ce ați întâlnit un trei, se va întoarce și va încerca să treacă prin calea zecimală. Acest lucru va funcționa, astfel încât o potrivire va fi găsită.

Algoritmul se oprește imediat ce găsește o potrivire completă. Aceasta înseamnă că, chiar dacă mai multe opțiuni pot fi potrivite, se folosește doar una dintre ele (în ordinea în care apar în secvența obișnuită).

Backtracking apare atunci când se utilizează operatori de repetiție precum + și *. Dacă căutați /^.*x/ în șirul „abcxe”, partea regex.* va încerca să consume întregul șir. Algoritmul va realiza apoi că are nevoie și de „x”. Deoarece nu există niciun „x” după sfârșitul șirului, algoritmul va încerca să caute o potrivire deplasând înapoi cu un caracter. După abcx nu există nici un x, apoi se întoarce din nou, de data aceasta la subșirul abc. Iar după linie, găsește x și raportează o potrivire reușită, în pozițiile 0 la 4.

Puteți scrie o rutină obișnuită care va duce la mai multe derulări. Această problemă apare atunci când modelul se poate potrivi cu intrarea în multe moduri diferite. De exemplu, dacă facem o greșeală când scriem expresia regulată pentru numere binare, s-ar putea să scriem accidental ceva de genul /(+)+b/.

Dacă algoritmul ar căuta un astfel de model într-un șir lung de 0 și 1 care nu avea un „b” la sfârșit, ar trece mai întâi prin bucla interioară până când rămâne fără cifre. Apoi va observa că nu există „b” la sfârșit, va întoarce o poziție înapoi, va trece prin bucla exterioară, va renunța din nou, va încerca să se întoarcă înapoi în altă poziție de-a lungul buclei interioare... Și va continua pentru a căuta în acest fel, folosind ambele bucle. Adică, cantitatea de lucru cu fiecare caracter al liniei se va dubla. Chiar și pentru câteva zeci de personaje, găsirea unei potriviri va dura foarte mult timp.

metoda înlocuirii

Șirurile au o metodă de înlocuire care poate înlocui o parte dintr-un șir cu un alt șir.

Console.log("tata".replace("p", "m")); // → hartă

Primul argument poate fi și o expresie regulată, caz în care prima apariție a expresiei regulate din linie este înlocuită. Când opțiunea „g” (globală) este adăugată la expresia regulată, toate aparițiile sunt înlocuite, nu doar prima

Console.log("Borobudur".replace(//, "a")); // → Barobudur console.log("Borobudur".replace(//g, "a")); // → Barabadar

Ar fi logic să treceți opțiunea „înlocuiți tot” printr-un argument separat sau printr-o metodă separată, cum ar fi înlocuiți toate. Dar, din păcate, opțiunea este transmisă prin sistemul obișnuit în sine.

Puterea deplină a expresiilor regulate este dezvăluită atunci când folosim link-uri către grupuri găsite într-un șir, specificate în expresia regulată. De exemplu, avem o linie care conține numele persoanelor, câte un nume pe rând, în formatul „Nume, Prenume”. Dacă trebuie să le schimbăm și să eliminăm virgula pentru a obține „Nume de familie”, scriem următoarele:

Console.log(„Hopper, Grace\nMcCarthy, John\nRitchie, Dennis” .replace(/([\w ]+), ([\w ]+)/g, „$2 $1”); // → Grace Hopper // John McCarthy // Dennis Ritchie

$1 și $2 în linia de înlocuire se referă la grupuri de caractere cuprinse între paranteze. $1 este înlocuit cu textul care se potrivește cu primul grup, $2 cu al doilea grup și așa mai departe, până la $9. Întreaga potrivire este conținută în variabila $&.

De asemenea, puteți trece o funcție ca al doilea argument. Pentru fiecare înlocuire, va fi apelată o funcție ale cărei argumente vor fi grupurile găsite (și toată partea corespunzătoare a liniei), iar rezultatul acesteia va fi inserat într-o nouă linie.

Exemplu simplu:

Var s = „cia și fbi”; console.log(s.replace(/\b(fbi|cia)\b/g, function(str) ( return str.toUpperCase(); ))); // → CIA și FBI

Iată una mai interesantă:

Stock de var = „1 lămâie, 2 varze și 101 ouă”; funcția minusOne(potrivire, cantitate, unitate) ( cantitate = Număr (cantitate) - 1; dacă (cantitate == 1) // a rămas doar unul, eliminați „s” de la sfârșit unit = unit.slice(0, unit. lungime - 1; else if (cantitate == 0) suma = "nu" + unitate) console.log(stock.replace(/(\d+)/g, minusOne); ); // → fără lămâie, 1 varză și 100 de ouă

Codul ia un șir, găsește toate aparițiile numerelor urmate de un cuvânt și returnează un șir cu fiecare număr redus cu unul.

Grupul (\d+) intră în argumentul cantitate, iar (\w+) intră în argumentul unitate. Funcția convertește suma într-un număr - și aceasta funcționează întotdeauna, deoarece modelul nostru este \d+. Și apoi face modificări la cuvânt, în cazul în care rămâne doar 1 articol.

Lăcomie

Este ușor de utilizat înlocuire pentru a scrie o funcție care elimină toate comentariile din codul JavaScript. Iată prima încercare:

Funcția stripComments(cod) ( return code.replace(/\/\/.*|\/\*[^]*\*\//g, ""); ) console.log(stripComments("1 + /* 2 */3")); // → 1 + 3 console.log(stripComments("x = 10;// zece!")); // → x = 10; console.log(stripComments("1 /* a */+/* b */ 1")); // → 1 1

Partea dinaintea operatorului „sau” se potrivește cu două bare oblice urmate de orice număr de caractere, cu excepția liniilor noi. Partea care elimină comentariile pe mai multe rânduri este mai complexă. Folosim [^], i.e. orice caracter care nu este gol ca o modalitate de a găsi orice personaj. Nu putem folosi un punct, deoarece comentariile de bloc continuă pe o linie nouă, iar caracterul de nouă linie nu se potrivește cu punctul.

Dar rezultatul exemplului anterior este incorect. De ce?

Partea [^]* va încerca mai întâi să captureze cât mai multe personaje. Dacă din această cauză următoarea parte a secvenței obișnuite nu găsește o potrivire, va derula un caracter înapoi și va încerca din nou. În exemplu, algoritmul încearcă să prindă întreaga linie, apoi se derulează înapoi. După ce a derulat înapoi 4 caractere, el va găsi */ în linie - și nu este ceea ce ne-am dorit. Am vrut să luăm un singur comentariu, și nu să mergem la sfârșitul rândului și să găsim ultimul comentariu.

Din această cauză, spunem că operatorii de repetiție (+, *, ? și ()) sunt lacomi, adică mai întâi apucă cât pot și apoi se întorc. Dacă puneți o întrebare după un astfel de operator (+?, *?, ??, ()?), ei se vor transforma în non-lacomi și vor începe să găsească cele mai mici apariții posibile.

Și de asta avem nevoie. Forțând asteriscul să găsească potriviri în numărul minim posibil de caractere dintr-o linie, consumăm doar un bloc de comentarii și nu mai mult.

Funcția stripComments(cod) ( return code.replace(/\/\/.*|\/\*[^]*?\*\//g, ""); ) console.log(stripComments("1 /* a */+/* b */ 1")); // → 1 + 1

Multe erori apar atunci când se folosesc operatori lacomi în loc de cei care nu sunt lacomi. Când utilizați operatorul de repetare, luați în considerare întotdeauna mai întâi operatorul non-lacom.

Crearea dinamică a obiectelor RegExp

În unele cazuri, modelul exact este necunoscut în momentul scrierii codului. De exemplu, va trebui să căutați numele utilizatorului în text și să-l încadrați în litere de subliniere. Deoarece veți ști numele numai după rularea programului, nu puteți utiliza notația oblică.

Dar puteți construi șirul și utilizați constructorul RegExp. Iată un exemplu:

Var nume = „harry”; var text = „Și Harry are o cicatrice pe frunte.”; var regexp = new RegExp("\\b(" + nume + ")\\b", "gi"); console.log(text.replace(regexp, "_$1_")); // → Și _Harry_ are o cicatrice pe frunte.

Când creăm limite de cuvinte, trebuie să folosim bare oblice duble pentru că le scriem într-o linie normală, și nu într-o secvență obișnuită cu bare oblice înainte. Al doilea argument la RegExp conține opțiuni pentru expresii regulate - în cazul nostru „gi”, adică. globală și fără majuscule.

Dar dacă numele este „dea+hlrd” (dacă utilizatorul nostru este un kulhatzker)? Ca rezultat, vom obține o expresie regulată fără sens care nu va găsi potriviri în șir.

Putem adăuga bare oblice inverse înaintea oricărui personaj care nu ne place. Nu putem adăuga bare oblice inverse înainte de litere deoarece \b sau \n sunt caractere speciale. Dar puteți adăuga bare oblice înaintea oricăror caractere non-alfanumerice fără probleme.

Var name = "dea+hlrd"; var text = "Acest dea+hlrd enervează pe toată lumea."; var escape = name.replace(/[^\w\s]/g, "\\$&"); var regexp = new RegExp("\\b(" + escape + ")\\b", "gi"); console.log(text.replace(regexp, "_$1_")); // → Această _dea+hlrd_ a enervat pe toată lumea.

metoda de cautare

Metoda indexOf nu poate fi utilizată cu expresii regulate. Dar există o metodă de căutare care așteaptă doar expresia regulată. La fel ca indexOf, returnează indexul primei apariții sau -1 dacă nu apare niciuna.

Console.log("cuvânt".search(/\S/)); // → 2 console.log(" ".search(/\S/)); // → -1

Din păcate, nu există nicio modalitate de a spune metodei să caute o potrivire începând cu un anumit offset (cum poți face cu indexOf). Asta ar fi de ajutor.

proprietate lastIndex

De asemenea, metoda exec nu oferă o modalitate convenabilă de a începe căutarea dintr-o poziție dată din șir. Dar oferă un mod incomod.

Un obiect regex are proprietăți. Una dintre ele este sursa, care conține un șir. Un altul este lastIndex, care controlează, în anumite condiții, unde va începe următoarea căutare a aparițiilor.

Aceste condiții includ faptul că opțiunea globală g trebuie să fie prezentă și că căutarea trebuie făcută folosind metoda exec. O soluție mai rezonabilă ar fi să permiteți pur și simplu să se transmită un argument suplimentar către exec, dar caracterul rezonabil nu este o caracteristică fundamentală a interfeței JavaScript regex.

Var model = /y/g; pattern.lastIndex = 3; var potrivire = pattern.exec("xyzzy"); console.log(match.index); // → 4 console.log(pattern.lastIndex); // → 5

Dacă căutarea a avut succes, apelul exec actualizează proprietatea lastIndex pentru a indica poziția după apariția găsită. Dacă nu a avut succes, lastIndex este setat la zero - la fel ca lastIndex al obiectului nou creat.

Când utilizați o variabilă obișnuită globală și apeluri multiple de exec, aceste actualizări automate lastIndex pot cauza probleme. Serverul dvs. obișnuit poate începe să caute din poziția rămasă de la apelul anterior.

Var digit = /\d/g; console.log(digit.exec ("aici este: 1")); // → ["1"] console.log(digit.exec("și acum: 1")); // → nul

Un alt efect interesant al opțiunii g este că schimbă modul în care funcționează metoda de potrivire. Când este apelat cu această opțiune, în loc să returneze o matrice similară cu rezultatul exec, găsește toate aparițiile modelului din șir și returnează o matrice a subșirurilor găsite.

Console.log("Banana".match(/an/g)); // → ["un", "un"]

Așa că aveți grijă cu variabilele globale regulate. Cazurile în care sunt necesare - înlocuiți apelurile sau locurile în care utilizați în mod specific lastIndex - sunt probabil toate cazurile în care ar trebui să fie utilizate.

Cicluri de apariție

O sarcină tipică este să iterați prin toate aparițiile unui model dintr-un șir, astfel încât să poată accesa obiectul potrivire din corpul buclei folosind lastIndex și exec.

Var input = "O linie cu 3 numere în ea... 42 și 88."; număr var = /\b(\d+)\b/g; var potrivire; while (potrivire = număr.exec(input)) console.log(„Găsit”, potrivire, „pe”, potrivire.index); // → Găsit 3 la 14 // Găsit 42 la 33 // Găsit 88 la 40

Profită de faptul că valoarea atribuirii este valoarea atribuită. Folosind match = re.exec(input) ca o condiție într-o buclă while, căutăm la începutul fiecărei iterații, stocăm rezultatul într-o variabilă și încheiem bucla când sunt găsite toate potrivirile.

Analizarea fișierelor INI

Pentru a încheia capitolul, să ne uităm la o problemă folosind expresii regulate. Imaginați-vă că scriem un program care colectează automat informații despre inamicii noștri prin Internet. (Nu vom scrie întregul program, ci doar partea care citește fișierul de setări. Ne pare rău.) Fișierul arată astfel:

Searchengine=http://www.google.com/search?q=$1 spitefulness=9.7 ; înaintea comentariilor se pune punct și virgulă; fiecare secțiune se referă la un inamic diferit nume complet=Larry Doe tip=website de taur de grădiniță=http://www.geocities.com/CapeCanaveral/11451 fullname=Gargamel type=evil wizard outputdir=/home/marijn/enemies/gargamel

Formatul exact de fișier (care este destul de utilizat pe scară largă și se numește de obicei INI) este următorul:

Liniile goale și liniile care încep cu punct și virgulă sunt ignorate
- liniile cuprinse între paranteze drepte încep o nouă secțiune
- linii care conțin un identificator alfanumeric urmat de = adăugați o setare în această secțiune

Toate celelalte sunt date incorecte.

Sarcina noastră este să convertim un astfel de șir într-o matrice de obiecte, fiecare cu o proprietate de nume și o matrice de setări. Este necesar un obiect pentru fiecare secțiune, iar altul este necesar pentru setările globale din partea de sus a fișierului.

Deoarece fișierul trebuie analizat linie cu linie, este o idee bună să începeți prin a împărți fișierul în linii. Pentru a face acest lucru, am folosit string.split("\n") în Capitolul 6. Unele sisteme de operare folosesc nu un caracter \n pentru întreruperi de linie, ci două - \r\n. Deoarece metoda split ia ca argument expresiile regulate, putem împărți linii folosind expresia /\r?\n/, permițând atât \n cât și \r\n între linii.

Funcția parseINI(șir) ( // Să începem cu un obiect care conține setări de nivel superior var currentSection = (nume: nul, câmpuri: ); var categorii = ; string.split(/\r?\n/).forEach(funcție (line ) ( var potrivire; if (/^\s*(;.*)?$/.test(line)) ( return; ) else if (match = line.match(/^\[(.*)\) ]$ /)) ( currentSection = (nume: potrivire, câmpuri: ); categories.push(currentSection); ) else if (potrivire = line.match(/^(\w+)=(.*)$/)) ( currentSection.fields.push((nume: potrivire, valoare: potrivire) else ( throw new Error("Linia "" + linia + "" conține date invalide."); ));

Codul parcurge toate liniile, actualizând obiectul secțiunii curente „secțiunea curentă”. În primul rând, verifică dacă linia poate fi ignorată folosind expresia regulată /^\s*(;.*)?$/. Vă puteți imagina cum funcționează asta? Partea dintre paranteze se potrivește cu comentariile, nu? face astfel încât caracterul obișnuit să se potrivească, de asemenea, linii formate doar din spații.

Dacă linia nu este un comentariu, codul verifică dacă începe o nouă secțiune. Dacă da, creează un nou obiect pentru secțiunea curentă, la care se adaugă setările ulterioare.

Ultima posibilitate semnificativă este ca șirul să fie o setare normală, caz în care este adăugat obiectului curent.

Dacă niciuna dintre opțiuni nu funcționează, funcția afișează o eroare.

Observați cum utilizarea frecventă a ^ și $ asigură că expresia se potrivește întregului șir, mai degrabă decât doar o parte a acestuia. Dacă nu le folosiți, codul va funcționa în general, dar uneori va produce rezultate ciudate și eroarea va fi dificil de găsit.

Construcția if (match = string.match(...)) este similară cu trucul de a folosi atribuirea ca condiție într-o buclă while. Adesea nu știi că apelul de potrivire va reuși, așa că poți accesa doar obiectul rezultat în interiorul unui bloc if care îl verifică. Pentru a nu rupe lanțul frumos al verificărilor if, atribuim rezultatul căutării unei variabile și folosim imediat această atribuire ca verificare.

Simboluri internaționale

Datorită implementării inițial simple a limbajului și fixării ulterioare a unei astfel de implementări „în granit”, expresiile regulate JavaScript sunt stupide cu caractere care nu se găsesc în limba engleză. De exemplu, caracterul „litera”, din punctul de vedere al expresiilor regulate JavaScript, poate fi una dintre cele 26 de litere ale alfabetului englez și, din anumite motive, și un caracter de subliniere. Litere precum é sau β, care sunt în mod clar litere, nu se potrivesc cu \w (și se vor potrivi cu \W, care este o non-litera).

Într-o întorsătură ciudată, din punct de vedere istoric, \s (spațiu) se potrivește cu toate caracterele care sunt considerate spații albe în Unicode, inclusiv lucruri precum spațiul care nu se întrerupe sau separatorul de vocale mongole.

Unele implementări regex în alte limbi au sintaxă specială pentru căutarea categoriilor speciale de caractere Unicode, cum ar fi „toate majuscule”, „toate semnele de punctuație” sau „caracterele de control”. Există planuri de a adăuga astfel de categorii la JavaScript, dar probabil că acestea nu vor fi implementate în curând.

Concluzie

Regularii sunt obiecte care reprezintă modele de căutare în șiruri. Ei folosesc propria sintaxă pentru a exprima aceste modele.

/abc/ Secvență de caractere
// Orice caracter din listă
/[^abc]/ Orice caracter, cu excepția caracterelor din listă
// Orice caracter din interval
/x+/ Una sau mai multe apariții ale modelului x
/x+?/ Una sau mai multe apariții, nelacom
/x*/ Zero sau mai multe apariții
/x?/ Zero sau o apariție
/x(2,4)/ De la două până la patru apariții
/(abc)/ Grup
/a|b|c/ Oricare dintre mai multe modele
/\d/ Orice număr
/\w/ Orice caracter alfanumeric („litera”)
/\s/ Orice caracter alb
/./ Orice caracter, cu excepția liniilor noi
/\b/ Limita cuvântului
/^/ Începutul liniei
/$/ Sfârșitul rândului

Regex are o metodă de testare pentru a verifica dacă modelul este în șir. Există o metodă exec care returnează o matrice care conține toate grupurile găsite. Matricea are o proprietate index, care conține numărul caracterului de la care a avut loc potrivirea.

Șirurile au o metodă de potrivire pentru a potrivi modelele și o metodă de căutare care returnează doar poziția de pornire a apariției. Metoda de înlocuire poate înlocui aparițiile unui model cu un alt șir. În plus, puteți trece o funcție de înlocuit care va construi o linie de înlocuire pe baza șablonului și a grupurilor găsite.

Caracterele obișnuite au setări care sunt scrise după bara oblică de închidere. Opțiunea i face ca expresia regulată să nu țină seama de majuscule și minuscule, iar opțiunea g o face globală, ceea ce, printre altele, face ca metoda de înlocuire să înlocuiască toate aparițiile găsite, nu doar prima.

Constructorul RegExp poate fi folosit pentru a crea expresii regulate din șiruri.

Regulatoarele sunt un instrument ascuțit cu un mâner inconfortabil. Ele simplifică foarte mult unele sarcini și pot deveni de negestionat atunci când rezolvăm alte probleme complexe. O parte a învățării să folosești regexe este să poți rezista tentației de a le umple cu o sarcină pentru care nu sunt destinate.

Exerciții

Inevitabil, atunci când rezolvi probleme, vei întâlni cazuri de neînțeles, iar uneori s-ar putea să disperi când vezi comportamentul imprevizibil al unor expresii regulate. Uneori ajută să studiezi comportamentul unui motor obișnuit printr-un serviciu online precum debuggex.com, unde poți vedea vizualizarea acestuia și îl poți compara cu efectul dorit.
Golf obișnuit
„Golf” în cod este un joc în care trebuie să exprimi un anumit program într-un număr minim de caractere. Golful obișnuit este un exercițiu practic de a scrie cei mai mici obișnuiți posibil pentru a găsi un model dat și doar atât.

Pentru fiecare dintre sublinii, scrieți o expresie regulată pentru a verifica locația lor în linie. Motorul obișnuit ar trebui să găsească numai aceste subșiruri specificate. Nu vă faceți griji cu privire la limitele cuvintelor decât dacă sunt menționate în mod specific. Când aveți un model obișnuit de lucru, încercați să îl reduceți.

Mașină și pisică
- pop și prop
- dihor, feribot și ferrari
- Orice cuvânt care se termină în ious
- Un spațiu urmat de un punct, virgulă, două puncte sau punct și virgulă.
- Un cuvânt mai lung de șase litere
- Cuvânt fără litere e

// Introduceți expresiile regulate verify(/.../, ["mașina mea", "pisicile rele"], ["camper", "high art"]); verifică(/.../, ["cultură pop", "recuzită nebună"], ["plop"]); verifica(/.../, ["dihor", "feribot", "ferrari"], ["ferrum", "transfer A"]); verifica(/.../, [„cât de delicios”, „cameră spațioasă”], [„ruinator”, „conștiință”]); verifică(/.../, ["punctuație proastă."], ["escape the dot"]); verifică(/.../, ["hottenottententen"], ["nu", "hotten totten tenten"]); verifică(/.../, [„ornitorinc roșu”, „cuib clătinat”], [„pat de pământ”, „maimuță care învață”]); function verify(regexp, yes, no) ( // Ignora exercitiile neterminate daca (regexp.source == "...") return; yes.forEach(function(s) ( if (!regexp.test(s))) consola .log("Nu a fost găsită "" + s + """ )); ); ));

Citate în text
Să presupunem că ați scris o poveste și ați folosit ghilimele simple pentru a indica dialogul. Acum doriți să înlocuiți ghilimelele de dialog cu ghilimele duble și să lăsați ghilimele simple în abrevieri ale cuvintelor precum aren’t.

Veniți cu un model care să facă distincția între aceste două utilizări ale ghilimelelor și scrieți un apel la metoda înlocuire care face înlocuirea.

Din nou numere
Secvențele de numere pot fi găsite cu o expresie regulată simplă /\d+/.

Scrieți o expresie care găsește numai numere scrise în stil JavaScript. Trebuie să suporte un posibil minus sau plus înaintea numărului, un punct zecimal și notația științifică 5e-3 sau 1E10 - din nou cu un posibil plus sau minus. De asemenea, rețineți că este posibil să nu existe neapărat numere înainte sau după punct, dar numărul nu poate consta dintr-un singur punct. Adică, .5 sau 5. sunt numere valide, dar un punct în sine nu este.

// Introduceți secvența obișnuită aici. var număr = /^...$/; // Teste: ["1", "-1", "+15", "1.55", ".5", "5.", "1.3e2", "1E-4", "1e+12"] .forEach(funcție(i) ( dacă (!număr.test(e)) console.log("Nu am găsit "" + s + """); )); ["1a", "+-1", "1.2.3", "1+1", "1e4.5", ".5.", "1f5", "."].forEach(funcție(i) ( if (număr.test(e)) console.log("Acceptat incorect "" + s + """); ));

În JavaScript, expresiile regulate sunt reprezentate de obiecte RegExp. Obiectele RegExp pot fi create folosind constructorul RegExp(), dar mai des sunt create folosind o sintaxă literală specială. Așa cum literalele șir sunt specificate ca caractere cuprinse între ghilimele, literalele expresii regulate sunt specificate ca caractere incluse într-o pereche de bară oblică / .

/pattern/flags new RegExp(„model”[, opțiuni de căutare])

model- o expresie obișnuită pentru căutare (mai multe despre înlocuire mai târziu) și steaguri - un șir de orice combinație de caractere g (căutare globală), i (măjuscule nu sunt importante) și m (căutare pe mai multe linii). Prima metodă este folosită des, a doua - uneori. De exemplu, două astfel de apeluri sunt echivalente.

optiuni de cautare

Când creăm o expresie regulată, putem specifica opțiuni de căutare suplimentare

Caractere din expresiile regulate JavaScript

SimbolCorespondenţă
Caractere alfanumericeCorespunde lor înșiși
\0 Caracter NUL (\u0000)
\tFilă (\u0009)
\nFlux de linie (\u000A)
\vFilă verticală (\u000B)
\fTraducerea paginii (\u000C)
\rRetur transport (\u000D)
\xnnset de caractere latine număr hexazecimal nn; de exemplu, \x0A este același cu \n
\uxxxxCaracter Unicode specificat de numărul hexazecimal xxxx; de exemplu, \u0009 este același cu \t
\cXCaracterul de control „X”, de exemplu, secvența \cJ este echivalentă cu caracterul newline \n
\ Pentru personajele obișnuite - le face speciale. De exemplu, expresia /s/ caută pur și simplu caracterul „s”. Și dacă puneți \ înainte de s, atunci /\s/ indică deja un caracter de spațiu Și invers, dacă caracterul este special, de exemplu *, atunci \ îl va face doar un caracter „asterisc” obișnuit. De exemplu, /a*/ caută 0 sau mai multe caractere „a” consecutive. Pentru a găsi un cu asterisc „a*” - pune \ în fața specialului. simbol: /a\*/ .
^ Indică începutul datelor de intrare. Dacă este setat indicatorul de căutare pe mai multe linii ("m"), se va declanșa și la începutul unei noi linii. De exemplu, /^A/ nu va găsi "A" în "un A", dar va găsi primul „A” în „An A”.
$ Indică sfârșitul datelor de intrare. Dacă este setat indicatorul de căutare pe mai multe linii, acesta va funcționa și la sfârșitul liniei. De exemplu, /t$/ nu va găsi „t” în „eater”, dar îl va găsi în „eat”.
* Indică repetarea de 0 sau mai multe ori. De exemplu, /bo*/ va găsi „buuuuuuuuuuuuuuuluuuuuuuuuuuuuuulhului” în „A fantomă huiduită” și „b” în „A bird warbled”, dar nu va găsi nimic în „O capră a mormăit”.
+ Indică repetarea de 1 sau mai multe ori. Echivalent cu (1,). De exemplu, /a+/ se va potrivi cu „a” din „bomboane” și cu toate „a” din „caaaaaaandy”.
? Indică faptul că elementul poate fi prezent sau nu. De exemplu, /e?le?/ se va potrivi cu „el” în „înger” și „le” în „unghi”. , sau () , apoi specifică o căutare „non-lacomă” (repetând numărul minim posibil de ori, la cel mai apropiat element următor al modelului), spre deosebire de modul implicit „lacom”, în care numărul de repetări este maxim, chiar dacă elementul următor modelul este, de asemenea, potrivit. utilizat în previzualizare, care este descrisă în tabel de sub (?=) , (?!) și (?:) .
. (Punctul zecimal) reprezintă orice caracter, altul decât o linie nouă: \n \r \u2028 sau \u2029. (puteți folosi [\s\S] pentru a căuta orice caracter, inclusiv linii noi). De exemplu, /.n/ se va potrivi cu „an” și „on” în „nu, un măr este pe copac”, dar nu „nu”.
(X)Găsește x și își amintește. Aceasta se numește „paranteze de memorie”. De exemplu, /(foo)/ va găsi și își va aminti „foo” în „foo bar”. Subșirul găsit este stocat în matricea rezultatelor căutării sau în proprietățile predefinite ale obiectului RegExp: $1, ..., $9 În plus, parantezele combină ceea ce este conținut în ele într-un singur element de model. De exemplu, (abc)* - repetă abc 0 sau de mai multe ori.
(?:X)Găsește x, dar nu își amintește ce găsește. Aceasta se numește „paranteze de memorie”. Subșirul găsit nu este stocat în matricea de rezultate și în proprietățile RegExp Ca toate parantezele, ele combină ceea ce este în ele într-un singur submodel.
x(?=y)Găsește x numai dacă x este urmat de y. De exemplu, /Jack(?=Sprat)/ se va potrivi doar cu „Jack” dacă este urmat de „Sprat”. /Jack(?=Sprat|Frost)/ se va potrivi doar cu „Jack” dacă este urmat de „Sprat” sau „Frost”. Cu toate acestea, nici „Sprat” și nici „Frost” nu vor apărea în rezultatul căutării.
X y)Găsește x numai dacă x nu este urmat de y. De exemplu, /\d+(?!\.)/ se va potrivi doar cu un număr dacă nu este urmat de un punct zecimal. /\d+(?!\.)/.exec("3.141") va găsi 141, dar nu 3.141.
x|yGăsește x sau y. De exemplu, /verde|roșu/ se va potrivi cu „verde” în „măr verde” și „roșu” în „măr roșu”.
(n)Unde n este un număr întreg pozitiv. Găsește exact n repetări ale elementului precedent. De exemplu, /a(2)/ nu va găsi „a” în „bomboane”, dar va găsi atât a în „caandy”, cât și primele două a în „caaandy”.
(n,)Unde n este un număr întreg pozitiv. Găsește n sau mai multe repetări ale unui element. De exemplu, /a(2,) nu va găsi „a” în „bomboane”, dar va găsi toate „a” în „caandy” și în „caaaaaaandy”.
(n,m)Unde n și m sunt numere întregi pozitive. Găsiți de la n la m repetări ale elementului.
Set de caractere. Găsește oricare dintre personajele enumerate. Puteți indica spațierea folosind o liniuță. De exemplu, - la fel ca . Se potrivește „b” în „piept” și „a” și „c” în „durere”.
[^xyz]Orice caracter altul decât cele specificate în set. De asemenea, puteți specifica un interval. De exemplu, [^abc] este același cu [^a-c] . Găsește „r” în „piept” și „h” în „chop”.
[\b]Găsește caracterul backspace. (A nu se confunda cu \b .)
\bGăsește o limită a unui cuvânt (latină), cum ar fi un spațiu. (A nu se confunda cu [\b]). De exemplu, /\bn\w/ se va potrivi cu „nu” în „amiază”; /\wy\b/ va găsi „ly” în „posibil ieri”.
\BNu indică o limită de cuvânt. De exemplu, /\w\Bn/ se va potrivi cu „on” în „noonday”, iar /y\B\w/ se va potrivi cu „ye” în „eventual ieri”.
\cXUnde X este o literă de la A la Z. Indică un caracter de control într-un șir. De exemplu, /\cM/ reprezintă caracterul Ctrl-M.
\dgăsește un număr din orice alfabet (al nostru este Unicode). Utilizați pentru a găsi numai numere obișnuite. De exemplu, /\d/ sau // se va potrivi cu „2” din „B2 este numărul suită”.
\DGăsește un caracter nenumeric (toate alfabetele). [^0-9] este echivalentul pentru numerele regulate. De exemplu, /\D/ sau /[^0-9]/ se va potrivi cu „B” din „B2 este numărul suitei”.
\sGăsește orice caracter de spațiu alb, inclusiv spațiu, tabulator, linie nouă și alte caractere de spațiu alb Unicode. De exemplu, /\s\w*/ se va potrivi cu „bar” în „foo bar”.
\SGăsește orice caracter, cu excepția spațiului alb. De exemplu, /\S\w*/ se va potrivi cu „foo” în „foo bar”.
\vCaracter de filă verticală.
\wGăsește orice caracter de cuvânt (alfabet latin), inclusiv litere, cifre și caractere de subliniere. Echivalent. De exemplu, /\w/ se va potrivi cu „a” în „măr”, „5” în „5,28 USD” și „3” în „3D”.
\WGăsește orice caracter verbal non-(latin). Echivalent cu [^A-Za-z0-9_] . De exemplu, /\W/ și /[^$A-Za-z0-9_]/ se vor potrivi în mod egal cu „%” în „50%”.

Lucrul cu expresii regulate în Javascript

Lucrul cu expresii regulate în Javascript este implementat prin metodele clasei String

exec(regexp) - găsește toate potrivirile (intrările din modelul obișnuit) într-un șir. Returnează o matrice (dacă există o potrivire) și actualizează proprietatea regexp, sau null dacă nu se găsește nimic. Cu modificatorul g - de fiecare dată când această funcție este apelată, va returna următoarea potrivire după cea anterioară găsită - aceasta este implementată prin menținerea unui index de offset al ultimei căutări.

match(regexp) - găsiți o parte dintr-un șir folosind un model. Dacă este specificat modificatorul g, atunci match() returnează o matrice cu toate potrivirile sau null (mai degrabă decât o matrice goală). Fără modificatorul g, această funcție funcționează ca exec();

test(regexp) - funcția verifică un șir pentru a se potrivi cu un model. Returnează adevărat dacă există o potrivire și false dacă nu există potrivire.

split(regexp) - împarte șirul la care este apelat într-o matrice de subșiruri, folosind argumentul ca delimitator.

replace(regexp, mix) - metoda returnează un șir modificat în conformitate cu șablonul (expresie regulată). Primul parametru al expresiei regulate poate fi, de asemenea, un șir, mai degrabă decât o expresie regulată. Fără modificatorul g, metoda din linie înlocuiește doar prima apariție; cu modificatorul g - are loc o înlocuire globală, adică. toate aparițiile unei linii date sunt modificate. mix - șablon de înlocuire, poate accepta valorile unui șir, șablon de înlocuire, funcție (numele funcției).

Caractere speciale în șirul de înlocuire

Înlocuire prin funcție

Dacă specificați o funcție ca al doilea parametru, aceasta este executată la fiecare potrivire. O funcție poate genera și returna dinamic un șir de substituție. Primul parametru al funcției este subșirul găsit. Dacă primul argument de înlocuit este un obiect RegExp, atunci următorii n parametri conțin paranteze imbricate potriviri. Ultimii doi parametri sunt poziția în linia în care a avut loc potrivirea și linia în sine.

  • Serghei Savenkov

    un fel de recenzie „scurtă”... de parcă ne-am grăbi pe undeva