Příklady regulárních výrazů Javascriptu. Regulární výrazy JavaScriptu. Praktické využití: zpracování e-mailů

Regulární výrazy

Regulární výraz je objekt, který popisuje vzor znaků. Třída RegExp v JavaScriptu představuje regulární výrazy a objekty tříd String a RegExp definují metody, které používají regulární výrazy k provádění porovnávání vzorů a vyhledávání a nahrazování textu. Gramatika regulárních výrazů JavaScriptu obsahuje poměrně kompletní podmnožinu syntaxe regulárních výrazů používané v Perlu 5, takže pokud máte zkušenosti s Perlem, můžete snadno psát vzory v programech JavaScript.

Funkce regulárních výrazů Perlu, které nejsou podporovány v ECMAScriptu, zahrnují příznaky s (jednořádkový režim) a x (rozšířená syntaxe); escape sekvence \a, \e, \l, \u, \L, \U, \E, \Q, \A, \Z, \z a \G a další rozšířené konstrukce začínající na (?.

Definování regulárních výrazů

V JavaScriptu jsou regulární výrazy reprezentovány objekty RegExp. Objekty RegExp lze vytvořit pomocí konstruktoru RegExp(), ale častěji jsou vytvořeny pomocí speciální doslovné syntaxe. Stejně jako jsou řetězcové literály zadány jako znaky ohraničené uvozovkami, literály regulárních výrazů jsou určeny jako znaky ohraničené dvojicí lomítek (/). Váš kód JavaScript tedy může obsahovat řádky jako tento:

Vzor var = /s$/;

Tento řádek vytvoří nový objekt RegExp a přiřadí jej k proměnné vzor. Tento objekt RegExp hledá všechny řetězce končící znakem "s". Stejný regulární výraz lze definovat pomocí konstruktoru RegExp():

Vzor var = new RegExp("s$");

Specifikace vzoru regulárního výrazu se skládá ze sekvence znaků. Většina znaků, včetně všech alfanumerických, doslova popisuje znaky, které musí být přítomny. To znamená, že regulární výraz /java/ odpovídá všem řádkům obsahujícím podřetězec „java“.

Jiné znaky v regulárních výrazech nejsou určeny k nalezení jejich přesných ekvivalentů, ale mají spíše speciální význam. Například regulární výraz /s$/ obsahuje dva znaky. První znak s označuje hledání doslovného znaku. Za druhé, $ je speciální metaznak, který označuje konec řádku. Tento regulární výraz tedy odpovídá libovolnému řetězci končícímu znakem s.

Následující části popisují různé znaky a metaznaky používané v regulárních výrazech v JavaScriptu.

Doslovné postavy

Jak bylo uvedeno dříve, všechny abecední znaky a čísla v regulárních výrazech se shodují. Syntaxe regulárních výrazů v JavaScriptu také podporuje možnost specifikovat určité neabecední znaky pomocí escape sekvencí začínajících znakem zpětného lomítka (\). Například sekvence \n odpovídá znaku nového řádku. Tyto symboly jsou uvedeny v tabulce níže:

Některá interpunkční znaménka mají v regulárních výrazech zvláštní význam:

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

Význam těchto symbolů je vysvětlen v následujících částech. Některé z nich mají zvláštní význam pouze v určitých kontextech regulárních výrazů, zatímco v jiných kontextech jsou interpretovány doslovně. Obecně však platí, že chcete-li doslovně zahrnout některý z těchto znaků do regulárního výrazu, musíte mu předcházet znak zpětného lomítka. Jiné znaky, jako jsou uvozovky a @, nemají žádný zvláštní význam a jednoduše se shodují v regulárních výrazech.

Pokud si přesně nepamatujete, kterým znakům by mělo předcházet \, můžete před kterýkoli ze znaků bezpečně vložit zpětné lomítko. Mějte však na paměti, že mnoho písmen a číslic nabývá zvláštních významů v kombinaci se znakem lomítka, takže písmena a čísla, která doslova hledáte, by neměly předcházet znak \. Chcete-li do regulárního výrazu zahrnout samotný znak zpětného lomítka, musíte mu samozřejmě předcházet další znak zpětného lomítka. Například následující regulární výraz odpovídá libovolnému řetězci, který obsahuje znak zpětného lomítka: /\\/.

Třídy postav

Jednotlivé doslovné znaky lze jejich umístěním kombinovat do tříd znaků hranaté závorky. Třída znaků odpovídá libovolnému znaku obsaženému v této třídě. Regulární výraz // tedy odpovídá jednomu ze znaků a, b nebo c.

Třídy záporných znaků lze také definovat tak, aby odpovídaly jakémukoli znaku kromě těch, které jsou uvedeny v závorkách. Třída znaků negace je určena znakem ^ jako prvním znakem za levou závorkou. Regulární výraz /[^abc]/ odpovídá libovolnému znaku kromě a, b nebo c. Ve znakových třídách lze rozsah znaků zadat pomocí pomlčky. Všechna malá písmena latinky lze nalézt pomocí výrazu // a jakékoli písmeno nebo číslo ze znakové sady latinky lze nalézt pomocí výrazu //.

Některé třídy znaků jsou obzvláště běžné, takže syntaxe regulárních výrazů v JavaScriptu obsahuje speciální znaky a sekvence escape, které je reprezentují. \s tedy odpovídá mezerě, tabulátoru a jakýmkoli bílým znakům Unicode a \S odpovídá všem znakům mezer v Unicode.

Níže uvedená tabulka obsahuje seznam těchto speciálních znaků a syntaxi tříd znaků. (Upozorňujeme, že některé sekvence escape třídy znaků odpovídají pouze znakům ASCII a nejsou rozšířeny tak, aby fungovaly se znaky Unicode. Můžete explicitně definovat své vlastní třídy znaků Unicode, například /[\u0400-\u04FF]/ odpovídá libovolnému znaku azbuky .)

Třídy znaků s regulárním výrazem v JavaScriptu
Symbol Korespondence
[...] Kterýkoli ze znaků uvedených v závorkách
[^...] Kterýkoli ze znaků neuvedených v závorkách
. Jakýkoli znak jiný než nový řádek nebo jiný oddělovač řádků Unicode
\w Libovolný textový znak ASCII. Ekvivalent
\W Jakýkoli znak, který není textovým znakem ASCII. Ekvivalentní [^a-zA-Z0-9_]
\s Libovolný znak mezery ze sady Unicode
\S Libovolný znak bez mezer ze sady Unicode. Upozorňujeme, že znaky \w a \S nejsou totéž
\d Jakákoli čísla ASCII. Ekvivalent
\D Jakýkoli znak jiný než čísla ASCII. Ekvivalentní [^0-9]
[\b] Doslovný znak backspace

Všimněte si, že escape sekvence speciální znaky třídy mohou být v hranatých závorkách. \s odpovídá libovolnému znaku mezery a \d libovolné číslici, proto /[\s\d]/ odpovídá libovolnému znaku mezery nebo číslici.

Opakování

Vzhledem k dosud získaným znalostem syntaxe regulárních výrazů můžeme dvoumístné číslo popsat jako /\d\d/ nebo čtyřmístné jako /\d\d\d\d/, ale neumíme např. , popisují číslo skládající se z libovolného počtu číslic nebo řetězce tří písmen, za nimiž následuje volitelná číslice. Tyto složitější vzory používají syntaxi regulárního výrazu, která určuje, kolikrát lze daný prvek regulárního výrazu opakovat.

Opakované symboly vždy sledují vzor, ​​na který jsou aplikovány. Některé typy opakování se používají poměrně často a pro označení těchto případů jsou k dispozici speciální symboly. Například + odpovídá jedné nebo více instancím předchozího vzoru. Následující tabulka obsahuje souhrn syntaxe opakování:

Na následujících řádcích je uvedeno několik příkladů:

Vzor var = /\d(2,4)/; // Odpovídá číslu obsahujícímu dvě až čtyři číslice vzor = /\w(3)\d?/; // Shodujte přesně tři znaky slova a jeden volitelný vzor číslic = /\s+java\s+/; // Odpovídá slovu "java" s jednou nebo více mezerami // před a za ním pattern = /[^(]*/; // Odpovídá nule nebo více znakům jiným než úvodní závorka

Buďte opatrní při používání opakujících se znaků * a ?. Mohou odpovídat absenci vzoru specifikovaného před nimi, a tedy absenci znaků. Například regulární výraz /a*/ odpovídá řetězci „bbbb“, protože neobsahuje znak a.

Znaky opakování uvedené v tabulce představují maximální možný počet opakování, který umožní shodu následujících částí regulárního výrazu. Říkáme, že je to chamtivé opakování. Je také možné realizovat opakování prováděné nezištným způsobem. Stačí za symbolem (nebo symboly) uvést opakování otazník: ??, +?, *? nebo dokonce (1,5)?.

Například regulární výraz /a+/ odpovídá jednomu nebo více výskytům písmene a. Při použití na řetězec "aaa" odpovídá všem třem písmenům. Na druhou stranu výraz /a+?/ se shoduje s jedním nebo více výskyty písmene a a vybere co nejméně počet znaků. Při použití na stejný řetězec se tento vzor shoduje pouze s prvním písmenem a.

„Nenasytné“ opakování ne vždy přináší očekávaný výsledek. Zvažte vzor /a+b/, který odpovídá jednomu nebo více a následovaným b. Při aplikaci na řetězec "aaab" odpovídá celému řetězci.

Nyní se podíváme na "nechamtivou" verzi /a+?b/. Někdo by si mohl myslet, že se bude shodovat s ab, kterému předchází pouze jedno a. Pokud se použije na stejný řetězec, očekává se, že „aaab“ bude odpovídat jedinému znaku a a poslednímu znaku b. Tento vzor však ve skutečnosti odpovídá celému řetězci, stejně jako lakomá verze. Faktem je, že vyhledávání vzoru regulárního výrazu se provádí nalezením první pozice v řetězci, od které je možná shoda. Vzhledem k tomu, že shoda je možná počínaje prvním znakem řetězce, kratší shody začínající od následujících znaků se ani neberou v úvahu.

Alternativy, seskupení a odkazy

Gramatika regulárních výrazů obsahuje speciální znaky pro definování alternativ, seskupování podvýrazů a odkazy na předchozí podvýrazy. Symbol potrubí | slouží k oddělení alternativ. Například /ab|cd|ef/ odpovídá buď řetězci "ab", nebo řetězci "cd", nebo řetězci "ef" a vzor /\d(3)|(4)/ odpovídá buď třem číslicím nebo čtyři malá písmena.

Všimněte si, že alternativy jsou zpracovávány zleva doprava, dokud není nalezena shoda. Pokud je nalezena shoda s levou alternativou, pravá je ignorována, i když lze dosáhnout „lepší“ shody. Proto, když je vzor /a|ab/ aplikován na řetězec "ab", bude odpovídat pouze prvnímu znaku.

Závorky mají v regulárních výrazech více významů. Jedním z nich je seskupování jednotlivých prvků do jednoho podvýrazu tak, aby prvky při použití speciálních znaků |, *, +, ? a ostatní jsou považovány za jeden celek. Vzor /java(script)?/ se například shoduje se slovem „java“ následovaným nepovinným slovem „script“ a /(ab|cd)+|ef)/ odpovídá buď řetězci „ef“ nebo jednomu či více opakování jednoho ze řetězců "ab" nebo "cd".

Dalším použitím závorek v regulárních výrazech je definování dílčích vzorů v rámci vzoru. Když je v cílovém řetězci nalezena shoda regulárního výrazu, lze extrahovat část cílového řetězce, která odpovídá jakémukoli konkrétnímu dílčímu vzoru uzavřenému v závorkách.

Předpokládejme, že chcete najít jedno nebo více malých písmen následovaných jedním nebo více čísly. K tomu můžete použít šablonu /+\d+/. Ale předpokládejme také, že chceme pouze čísla na konci každého zápasu. Pokud dáme tuto část vzoru do závorek (/+(\d+)/), můžeme extrahovat čísla ze všech nalezených shod. Jak se to dělá, bude popsáno níže.

Související použití závorkových podvýrazů je odkazovat na podvýrazy z předchozí části stejného regulárního výrazu. Toho je dosaženo zadáním jedné nebo více číslic za znakem \. Čísla označují pozici podvýrazu v závorkách v rámci regulárního výrazu. Například \1 odkazuje na první podvýraz a \3 odkazuje na třetí. Všimněte si, že podvýrazy lze vnořovat do sebe, takže při počítání se používá pozice levé závorky. Například v následujícím regulárním výrazu bude vnořený odkaz na podvýraz (kript) vypadat takto \2:

/(ava(kript)?)\sis\s(zábava\w*)/

Odkaz na předchozí podvýraz neukazuje na vzor tohoto podvýrazu, ale na nalezený text, který tomuto vzoru odpovídá. Proto lze odkazy použít k zavedení omezení, které vybere části řetězce, které obsahují přesně stejné znaky. Například následující regulární výraz odpovídá žádnému nebo více znakům uvnitř jednoduchých nebo dvojitých uvozovek. Nevyžaduje však, aby se úvodní a závěrečné uvozovky vzájemně shodovaly (to znamená, že obě uvozovky jsou jednoduché nebo dvojité):

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

Můžeme požadovat, aby se uvozovky shodovaly pomocí odkazu, jako je tento:

Zde \1 odpovídá prvnímu podvýrazu. V tomto příkladu odkaz zavádí omezení, které vyžaduje, aby koncová uvozovka odpovídala úvodní uvozovce. Tento regulární výraz neumožňuje jednoduché uvozovky uvnitř dvojitých uvozovek a naopak.

Je také možné seskupit prvky v regulárním výrazu, aniž byste na tyto prvky vytvořili číslovaný odkaz. Místo jednoduchého seskupování prvků mezi ( a ), začněte skupinu symboly (?: a ukončete ji symbolem). Zvažte například následující vzorec:

/(ava(?:cript)?)\sis\s(zábava\w*)/

Zde je podvýraz (?:cript) potřebný pouze pro seskupení, aby bylo možné na skupinu použít opakovací znak ? Tyto upravené závorky nevytvářejí odkaz, takže v tomto regulárním výrazu \2 odkazuje na text, který odpovídá vzoru (zábava\w*).

Následující tabulka uvádí výběrové, seskupovací a referenční operátory v regulárních výrazech:

Symboly regulárních výrazů pro výběr z alternativ, seskupování a JavaScript odkazy
Symbol Význam
| Alternativní. Odpovídá buď podvýrazu vlevo, nebo podvýrazu vpravo.
(...) Seskupování. Seskupuje prvky do jedné jednotky, kterou lze použít se znaky *, +, ?, | a tak dále. Také si pamatuje znaky odpovídající této skupině pro použití v následujících odkazech.
(?:...) Pouze seskupení. Seskupuje prvky do jedné jednotky, ale nepamatuje si znaky odpovídající této skupině.
\číslo Shoduje se se stejnými znaky, které byly nalezeny při porovnávání čísla skupiny. Skupiny jsou podvýrazy uvnitř (případně vnořených) závorek. Čísla skupin jsou přidělována počítáním levých závorek zleva doprava. Skupiny vytvořené pomocí symbolů (?:) se nečíslují.

Určení shodné pozice

Jak bylo popsáno dříve, mnoho prvků regulárního výrazu odpovídá jedinému znaku v řetězci. Například \s odpovídá jednomu prázdnému znaku. Jiné prvky regulárního výrazu odpovídají pozicím mezi znaky spíše než samotným znakům. Například \b odpovídá hranici slova – hranici mezi \w (textový znak ASCII) a \W (netextový znak) nebo hranici mezi textovým znakem ASCII a začátkem nebo koncem řádku.

Prvky jako \b neurčují žádné znaky, které musí být přítomny ve shodném řetězci, ale určují platné pozice pro shodu. Tyto prvky se někdy nazývají kotevní prvky regulárního výrazu, protože ukotvují vzor na konkrétní pozici v řetězci. Nejčastěji používané kotevní prvky jsou ^ a $, které spojují vzory se začátkem a koncem řádku.

Například slovo „JavaScript“ nalezené na samostatná linka, lze nalézt pomocí regulárního výrazu /^JavaScript$/. Chcete-li najít jediné slovo "Java" (spíše než předponu jako "JavaScript"), můžete zkusit použít vzor /\sJava\s/, který vyžaduje mezeru před a za slovem.

Takové řešení však vyvolává dva problémy. Za prvé, najde slovo „Java“ pouze tehdy, je-li obklopeno mezerami na obou stranách, a nebude jej moci najít na začátku nebo na konci řádku. Za druhé, když se tento vzor shoduje, řetězec, který vrací, bude obsahovat úvodní a koncové mezery, což není přesně to, co chceme. Takže namísto použití vzoru, který odpovídá mezerám \s, použijeme vzor (nebo kotvu), který odpovídá hranicím slov \b. ono to vyjde další výraz: /\bJava\b/.

Kotevní prvek \B odpovídá pozici, která není hranicí slova. To znamená, že vzor /\Bcript/ bude odpovídat slovům „JavaScript“ a „postscript“ a nebude odpovídat slovům „script“ nebo „Scripting“.

Libovolné regulární výrazy mohou také sloužit jako kotevní podmínky. Pokud mezi znaky (?= a) vložíte výraz, stane se to dopředným testem shody proti následným znakům, který vyžaduje, aby tyto znaky odpovídaly zadanému vzoru, ale nebyly zahrnuty do vyhledávacího řetězce.

Chcete-li například odpovídat názvu běžného programovacího jazyka, za kterým následuje dvojtečka, můžete použít výraz /ava(cript)?(?=\:)/. Tento vzor odpovídá slovu „JavaScript“ v řetězci „JavaScript: The Definitive Guide“, ale nebude odpovídat slovu „Java“ v řetězci „Java v kostce“, protože za ním nenásleduje dvojtečka.

Pokud zadáte podmínku (?!), bude se jednat o negativní dopřednou kontrolu následujících znaků, která vyžaduje, aby následující znaky neodpovídaly zadanému vzoru, například vzor /Java(?!Script)(\w*. )/ odpovídá podřetězci „Java“, za kterým následuje velké písmeno a libovolný počet textových znaků ASCII, za předpokladu, že za podřetězcem „Java“ nenásleduje podřetězec „Skript“ bude odpovídat řetězci „JavaBeans“. neodpovídá řetězci "Javanese", bude odpovídat řetězci "JavaScrip", ale nebude odpovídat řetězcům "JavaScript" nebo "JavaScripter".

Níže uvedená tabulka obsahuje seznam kotevních znaků regulárních výrazů:

Kotevní znaky regulárních výrazů
Symbol Význam
^ Odpovídá začátku řetězcového výrazu nebo začátku řádku při víceřádkovém vyhledávání.
$ Odpovídá konci řetězcového výrazu nebo konci řádku ve víceřádkovém vyhledávání.
\b Odpovídá hranici slova, tzn. odpovídá pozici mezi znakem \w a znakem \W nebo mezi znakem \w a začátkem nebo koncem řádku. (Všimněte si však, že [\b] odpovídá znaku backspace.)
\B Odpovídá pozici, která není hranicí slova.
(?=p) Pozitivní dopředná kontrola pro následující znaky. Vyžaduje následující znaky, aby odpovídaly vzoru p, ale nezahrnuje tyto znaky do shodného řetězce.
(?!p) Negativní dopředná kontrola pro následující znaky. Vyžaduje, aby následující znaky neodpovídaly vzoru p.

Vlajky

a ještě jeden, poslední prvek gramatiky regulárních výrazů. Příznaky regulárních výrazů určují pravidla pro porovnávání vzorů na vysoké úrovni. Na rozdíl od zbytku gramatiky regulárních výrazů nejsou příznaky specifikovány mezi znaky lomítka, ale za druhým. JavaScript podporuje tři příznaky.

Vlajka i určuje, že shoda vzorů by neměla rozlišovat malá a velká písmena a vlajka g- že vyhledávání má být globální, tzn. musí být nalezeny všechny shody v řetězci. Vlajka m provádí vyhledávání vzoru ve víceřádkovém režimu. Pokud hledaný řetězcový výraz obsahuje nové řádky, pak v tomto režimu kotevní znaky ^ a $, kromě toho, že odpovídají začátku a konci celého řetězcového výrazu, odpovídají také začátku a konci každého textového řádku. Například vzor /java$/im odpovídá jak „java“, tak „Java\nis fun“.

Tyto vlajky lze kombinovat v libovolné kombinaci. Chcete-li například vyhledat první výskyt slova „java“ (nebo „Java“, „JAVA“ atd.) bez ohledu na velikost písmen, můžete použít regulární výraz bez rozlišení velkých a malých písmen /\bjava\b/ i. A abyste našli všechny výskyty tohoto slova v řetězci, můžete přidat příznak g: /\bjava\b/gi.

Metody třídy String pro vyhledávání podle vzoru

Až do tohoto bodu jsme diskutovali o gramatice generovaných regulárních výrazů, ale nezkoumali jsme, jak lze tyto regulární výrazy ve skutečnosti použít ve skriptech JavaScript. V tato sekce Probereme metody objektu String, které používají regulární výrazy pro porovnávání vzorů a hledání s náhradou. A pak budeme pokračovat v rozhovoru o porovnávání vzorů s regulárními výrazy tím, že se podíváme na objekt RegExp a jeho metody a vlastnosti.

Řetězce podporují čtyři metody využívající regulární výrazy. Nejjednodušší z nich je metoda Vyhledávání(). Vezme regulární výraz jako argument a vrátí buď pozici prvního znaku shodného podřetězce, nebo -1, pokud není nalezena žádná shoda. Například následující volání vrátí 4:

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

Pokud argument metody search() není regulární výraz, je nejprve převeden předáním konstruktoru RegExp. Metoda search() nepodporuje globální vyhledávání a ignoruje příznak g ve svém argumentu.

Metoda nahradit() provede operaci hledání a nahrazení. Jako první argument bere regulární výraz a jako druhý náhradní řetězec. Metoda hledá na řádku, na kterém je volána, shodu se zadaným vzorem.

Pokud regulární výraz obsahuje příznak g, metoda replace() nahradí všechny nalezené shody náhradním řetězcem. V opačném případě nahradí pouze první nalezenou shodu. Pokud je prvním argumentem metody replace() spíše řetězec než regulární výraz, pak metoda provede doslovné hledání řetězce namísto jeho převodu na regulární výraz pomocí konstruktoru RegExp() jako metoda search().

Jako příklad můžeme použít metodu replace() ke konzistentnímu psaní velkých písmen slova „JavaScript“ v celém řádku textu:

// Bez ohledu na velikost písmen, nahradíme je slovem v požadovaném případě var result = "javascript".replace(/JavaScript/ig, "JavaScript");

Metoda replace() je výkonnější, než by tento příklad naznačoval. Dovolte mi připomenout, že podvýrazy v závorkách v rámci regulárního výrazu jsou číslovány zleva doprava a že regulární výraz si pamatuje text odpovídající každému z podvýrazů. Pokud náhradní řetězec obsahuje znak $ následovaný číslem, metoda nahradit() nahradí tyto dva znaky textem, který odpovídá zadanému podvýrazu. Toto je velmi užitečná příležitost. Můžeme jej použít například k nahrazení rovných uvozovek v řetězci typografickými uvozovkami, které jsou simulovány ASCII znaky:

// Citace je uvozovka, za kterou následuje libovolný počet znaků // kromě uvozovek (které si pamatujeme), po níž následuje další uvozovka // var quote = /"([^"]*)"/g; // Nahraďte rovné uvozovky s typografickými a ponechat "$1" beze změny // obsah citace uložený v $1 var text = ""JavaScript" je interpretovaný programovací jazyk."; var result = text.replace(quote, ""$1""; ) ; // "JavaScript" je interpretovaný programovací jazyk.

Důležité je poznamenat, že druhým argumentem pro náhradu() může být funkce, která dynamicky vypočítává náhradní řetězec.

Metoda zápas() je nejobecnější z metod třídy String, která používá regulární výrazy. Vezme regulární výraz jako svůj jediný argument (nebo převede svůj argument na regulární výraz předáním konstruktoru RegExp()) a vrátí pole obsahující výsledky hledání. Pokud je v regulárním výrazu nastaven příznak g, metoda vrátí pole všech shod přítomných v řetězci. Například:

// vrátí ["1", "2", "3"] var result = "1 plus 2 se rovná 3".match(/\d+/g);

Pokud regulární výraz neobsahuje příznak g, metoda match() neprovede globální vyhledávání; prostě to vypadá na první zápas. Match() však vrací pole, i když metoda neprovádí globální vyhledávání. V tomto případě je prvním prvkem pole nalezený podřetězec a všechny zbývající prvky jsou podvýrazy regulárního výrazu. Pokud tedy match() vrátí pole arr, pak arr bude obsahovat celý nalezený řetězec, arr podřetězec odpovídající prvnímu podvýrazu atd. Nakreslíme-li paralelu s metodou replace(), můžeme říci, že obsah $n je vložen do arr[n].

Podívejte se například na následující programový kód který analyzuje adresu URL:

Var url = /(\w+):\/\/([\w.]+)\/(\S*)/; var text = "Navštivte naše webové stránky http://www..php"; var vysledek = text.match(url); if (výsledek != null) ( var fullurl = výsledek; // Obsahuje "http://www..php" var protokol = výsledek; // Obsahuje "http" var hostitel = výsledek; // Obsahuje "www..php ")

Je třeba poznamenat, že pro regulární výraz, který nemá nastaven příznak globálního vyhledávání g, metoda match() vrací stejnou hodnotu jako metoda exec() regulárního výrazu: vrácené pole má vlastnosti index a input, jak je popsáno v diskuzi o exec() níže.

Poslední z objektových metod String, která používá regulární výrazy, je rozdělit(). Tato metoda rozdělí řetězec, na kterém je volána, na pole podřetězců, přičemž jako oddělovač použije argument. Například:

"123,456,789".split(","); // Návrat ["123","456","789"]

Metoda split() může také převzít regulární výraz jako argument. Díky tomu je metoda výkonnější. Můžete například zadat oddělovač, který umožňuje libovolný počet mezer na obou stranách:

"1, 2, 3, 4, 5".split(/\s*,\s*/); // Návrat ["1","2","3","4","5"]

RegExp objekt

Jak již bylo zmíněno, regulární výrazy jsou reprezentovány jako objekty RegExp. Kromě konstruktoru RegExp() podporují objekty RegExp tři metody a několik vlastností.

Konstruktor RegExp() vezme jeden nebo dva řetězcové argumenty a vytvoří nový objekt RegExp. Prvním argumentem konstruktoru je řetězec obsahující tělo regulárního výrazu, tzn. text, který se musí objevit mezi znaky lomítka v literálu regulárního výrazu. Všimněte si, že řetězcové literály a regulární výrazy používají znak \ k reprezentaci escape sekvencí, takže při předávání regulárního výrazu jako řetězcového literálu konstruktoru RegExp() musíte nahradit každý znak \ dvojicí znaků \\.

Druhý argument pro RegExp() může chybět. Pokud je zadán, definuje příznaky regulárního výrazu. Musí to být jeden ze znaků g, i, m nebo kombinace těchto znaků. Například:

// Najde všechna pěticiferná čísla v řetězci. Poznámka // použití symbolů v tomto příkladu \\ var zipcode = new RegExp("\\d(5)", "g");

Konstruktor RegExp() je užitečný, když je regulární výraz generován dynamicky, a proto jej nelze reprezentovat pomocí doslovné syntaxe regulárního výrazu. Chcete-li například najít řetězec zadaný uživatelem, musíte za běhu vytvořit regulární výraz pomocí funkce RegExp().

Vlastnosti RegExp

Každý objekt RegExp má pět vlastností. Vlastnictví zdroj- řetězec pouze pro čtení obsahující text regulárního výrazu. Vlastnictví globální je booleovská hodnota pouze pro čtení, která určuje, zda je příznak g přítomen v regulárním výrazu. Vlastnictví ignorovat případ je booleovská hodnota pouze pro čtení, která určuje, zda je příznak i přítomen v regulárním výrazu. Vlastnictví víceřádkový je booleovská hodnota pouze pro čtení, která určuje, zda je příznak m přítomen v regulárním výrazu. A poslední nemovitost lastIndex je celé číslo, které lze číst a zapisovat. U vzorů s příznakem g tato vlastnost obsahuje číslo pozice v řádku, na kterém má začít další hledání. Jak je popsáno níže, používají jej metody exec() a test().

Metody RegExp

Objekty RegExp definují dvě metody, které provádějí porovnávání vzorů; chovají se podobně jako výše popsané metody třídy String. Hlavní metoda třídy RegExp používaná pro porovnávání vzorů je exec(). Je podobná dříve zmíněné metodě match() třídy String, kromě toho, že se jedná o metodu třídy RegExp, která přebírá řetězec jako argument, spíše než metodu třídy String, která přebírá argument RegExp.

Metoda exec() provede regulární výraz pro zadaný řetězec, tzn. hledá shodu v řetězci. Pokud není nalezena žádná shoda, metoda vrátí hodnotu null. Pokud je však nalezena shoda, vrátí stejné pole jako pole vrácené metodou match() pro vyhledávání bez příznaku g. Nulový prvek pole obsahuje řetězec, který odpovídá regulárnímu výrazu, a všechny následující prvky obsahují podřetězce, které odpovídají všem podvýrazům. Kromě toho majetek index obsahuje číslo pozice znaku, kterým začíná odpovídající fragment, a vlastnost vstup odkazuje na řádek, který byl prohledán.

Na rozdíl od match() metoda exec() vrací pole, jehož struktura nezávisí na přítomnosti příznaku g v regulárním výrazu. Dovolte mi připomenout, že při předávání globálního regulárního výrazu metoda match() vrací pole nalezených shod. A exec() vždy vrátí jednu shodu, ale poskytne o ní informace úplné informace. Když je exec() volána na regulární výraz obsahující příznak g, metoda nastaví vlastnost lastIndex objektu regulárního výrazu na číslo pozice znaku bezprostředně za nalezeným podřetězcem.

Když je exec() voláno podruhé na stejném regulárním výrazu, začne hledání u znaku, jehož pozice je určena ve vlastnosti lastIndex. Pokud exec() nenajde shodu, vlastnost lastIndex je nastavena na 0. (LastIndex můžete také kdykoli nastavit na nulu, což by mělo být provedeno ve všech případech, kdy vyhledávání skončí dříve, než je poslední shoda v jednom řádku nalezen a hledání začíná na jiném řádku se stejným objektem RegExp.) Toto speciální chování umožňuje opakované volání exec() za účelem opakování všech shod regulárního výrazu v řádku. Například:

Vzor var = /Java/g; var text = "JavaScript je více legrační věc než Java!"; var result; while((result = vzor.exec(text)) != null) ( console.log("Nalezeno "" + výsledek + """ + " na pozici " + result.index + " ; další hledání začne od " + pattern.lastIndex);

Další metodou objektu RegExp je test(), což je hodně jednodušší metoda exec(). Vezme řetězec a vrátí hodnotu true, pokud řetězec odpovídá regulárnímu výrazu:

Vzor Var = /java/i; pattern.test("JavaScript"); // Návrat true

Volání test() je ekvivalentní volání exec(), které vrátí hodnotu true, pokud exec() vrátí něco jiného než null. Z tohoto důvodu se metoda test() při volání globálního regulárního výrazu chová stejně jako metoda exec(): začne hledat zadaný řetězec na pozici určené vlastností lastIndex, a pokud najde shodu , nastaví vlastnost lastIndex na číslo pozice znaku přímo vedle nalezené shody. Pomocí metody test() tedy můžete vytvořit smyčku procházení řádků stejným způsobem jako pomocí metody exec().

Tento článek popisuje základy používání regulárního výrazu v JavaScriptu.

Úvod

Co je regulární výraz?

Regulární výraz JS je posloupnost znaků, která tvoří pravidlo vyhledávání. Toto pravidlo pak lze použít k vyhledávání v textu i k jeho nahrazování. V praxi se regulární výraz může skládat i z jediného znaku, ale složitější vzory vyhledávání jsou běžnější.

V Javascriptu jsou regulární výrazy také objekty. Jedná se o vzory používané ke shodě sekvencí znaků v řetězcích. Používají se v metodách exec() a test() objektu RegExp a v metodách match(), replace(), search a split() objektu String.

Příklad

var vzor = /example/i

/example/i je regulární výraz. příkladem je šablona ( který bude použit při vyhledávání). i je modifikátor indikující rozlišování malých a velkých písmen.

Příprava regulárního výrazu

Regulární výrazy JS se skládají ze vzoru a modifikátoru. Syntaxe bude asi tato:

/vzor/modifikátory;

Šablona určuje pravidlo vyhledávání. Skládá se z jednoduchých znaků jako /abc/ nebo kombinace jednoduchých a speciálních znaků: /abc/ nebo /Chapter (d+).d/ .

Tabulka šablon

Modifikátory umožňují rozlišovat velká a malá písmena v dotazech, jsou globální a tak dále. Používají se k vyhledávání rozlišující malá a velká písmena i globální vyhledávání.

Tabulka modifikátorů


Nyní jsme připraveni použít regulární výrazy JS. Existují dva hlavní způsoby, jak toho dosáhnout: pomocí objektu regulárního výrazu nebo regulárního výrazu v řetězci.

Použití objektu regulárního výrazu

Vytvořte objekt regulárního výrazu

Tento objekt popisuje znakový vzor. Používá se pro párování vzorů. Objekt regulárního výrazu lze sestavit dvěma způsoby.

Metoda 1: Použití literálu regulárního výrazu, který se skládá ze vzoru uzavřeného lomítky, například:

var reg = /ab+c/;

Literály regulárního výrazu spouštějí při analýze skriptu předkompilaci regulárního výrazu. Pokud je regulární výraz konstantní, použijte jej ke zlepšení výkonu.

Metoda 2: Volání funkce konstruktoru objektu RegExp, například:

var reg = new RegExp("ab+c");

Použití konstruktoru umožňuje kompilaci regulárního výrazu JS za běhu skriptu. Tuto metodu použijte, pokud se regulární výraz změní nebo neznáte vzor předem. Pokud například obdržíte informace od uživatele, který zadá vyhledávací dotaz.

Metody objektů regulárních výrazů

Podívejme se na několik běžných metod objektů regulárních výrazů:

  • zkompilovat() ( zastaralé ve verzi 1.5) – přeloží regulární výraz;
  • exec() - Provede shodu řetězce. Vrátí první shodu;
  • test() - provede shodu na řetězci. Vrátí true nebo false ;
  • toString() – vrací hodnotu řetězce regulárního výrazu.

Příklady

Pomocí testu()

Metoda test() je regulární výraz objektu RegExp. Vyhledá řetězec vzoru a vrátí hodnotu true nebo false v závislosti na výsledku. Následující příklad regulárního výrazu JS ukazuje, jak se v řetězci hledá znak „ E”:

var patt = /e/; patt.test("Nejlepší věci na světě jsou zdarma!");

Protože zde v řadě je „ E“, výsledek tohoto kódu bude pravdivý.

Regulární výrazy nemusí být umístěny v proměnné. Stejný dotaz lze provést na jednom řádku:

/e/.test("Nejlepší věci na světě jsou zdarma!");

Použití exec()

Prohledá řetězec pomocí daného vyhledávacího pravidla a vrátí nalezený text. Pokud nebyly nalezeny žádné shody, bude výsledek null .

Podívejme se na metodu v akci na příkladu stejného symbolu “ E”:

/e/.exec("Nejlepší věci na světě jsou zdarma!");

Protože řádek obsahuje „ E“, výsledkem tohoto kódu bude .e .

Použití regulárního výrazu na řetězec

V Javascriptu lze tyto výrazy použít také se dvěma metodami objektu String: search() a replace(). Jsou potřebné k provádění vyhledávání a nahrazování v textu.

  • metoda search() - používá výraz k vyhledání shody a vrací informace o umístění shody;
  • Metoda replace() vrací upravený řetězec s nahrazeným vzorem.

Příklady

Použití regulárního výrazu JS k provedení vyhledávání fráze s rozlišováním velkých a malých písmen w3schools" v souladu:

var str = "Navštivte W3Schools"; var n = str.search(/w3schools/i);

Výsledek v n bude 6.

Metoda vyhledávání také bere jako argument řetězec. Řetězcový argument bude převeden na regulární výraz:

Použití řetězce k vyhledání fráze „ školy W3" v souladu:

var str = "Navštivte W3Schools!"; var n = str.search("W3Schools");

Použití regulárního výrazu JS rozlišujícího velká a malá písmena k nahrazení " Microsoft"zapnuto" W3Schools" v souladu:

var str = "Navštivte Microsoft!"; var res = str.replace(/microsoft/i, "W3Schools");

V důsledku toho dostaneme: „Navštivte W3Schools! ".

Metoda replace() také přijímá hledaný řetězec:

var str = “Navštivte Microsoft!”; var res = str.replace(“Microsoft”, “W3Schools”);

Překlad článku " Použití regulárního výrazu v Javascriptu“ připravil přátelský projektový tým

Regex nebo regulární výrazy jsou pro začátečníky zastrašující, ale pro každého programátora jsou nezbytné. Pojďme pochopit regulární výrazy v 5 jednoduché příklady s JavaScriptem.

Pokud máte problém a hodláte ho vyřešit regulárními výrazy, máte nyní dva problémy. Existuje rčení. Regulární výrazy nalezené v kódu někdy vyvolávají strach a nenávist u lidí, kteří je neznají.

Ale ve skutečnosti je jakýkoli regulární výraz pouze šablonovým výrazem, který dokáže vyřešit problém celé funkce na jednom řádku. Chcete-li však sestavit regulární výraz, musíte vzít v úvahu soubor přísných pravidel, ve kterých se začátečník může splést a udělat chyby.

Odpovídající postavy

Nejzákladnější regulární výrazy jsou ty, které odpovídají jednotlivým znakům. Zde jsou jejich pravidla:

1. Tečka (.) odpovídá libovolnému znaku. Pokud potřebujete vyhledat konkrétní bod, musíte jej opustit znakem „\“ (\.).

2. Otazník (?) označuje, že předchozí znak je volitelný. Chcete-li vyhledat otazník samotný v řetězci, musí být také escapován pomocí "\" (\?).

var text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit lest. Donec convallis dignissim ligula, et rutrum est elat vistibulum eu."; // Postačí „elit“ i „elat“. Tečka znamená, že se hodí jakýkoli symbol. var regex = /el.t/g; console.log(text.match(regulární výraz)); // "est" a "lest" budou fungovat stejně dobře. Otazník činí "l" volitelným. var regex2 = /l?est/g; console.log(text.match(regulární výraz2));

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

// Postačí „elit“ i „elat“. Tečka znamená, že se hodí jakýkoli symbol.

var regex = /el.t/g ;

řídicí panel. log(text. shoda(regulární výraz));

// "est" a "lest" budou fungovat stejně dobře. Otazník činí "l" volitelným.

var regex2 = /l?est/g ;

řídicí panel. log(text. shoda(regulární výraz2));

Spojte více znaků

Sada je jeden nebo více znaků uzavřených v závorkách, například . Tento výraz bude hledat pouze tuto sadu znaků v řetězci – v tomto příkladu pouze a, b nebo c. Naopak můžete vyhledávat výskyty libovolných symbolů kromě použití symbolu „^“. [^abc] bude odpovídat libovolnému znaku, který není a, b nebo c. Můžete také zadat rozsah znaků nebo čísel, například , .

Existují vestavěné znakové sady, které usnadňují psaní regulárních výrazů. Říká se jim zkratky nebo těsnopis. Místo toho můžete například napsat \D. Existují zkratky pro další znaky (včetně čísel a podtržítek) - \w a \W, stejně jako pro mezery - \s a \S.

// Fungovat bude pouze "kočka" a "can", nikoli "auto". var text = "kočičí konzerva"; console.log(text.match(/ca/g)); // Projde vše kromě cat a can (je tam symbol ^) console.log(text.match(/ca[^tn]/g)); // Další příklad, kdy projdou pouze čísla text = "Chtěl bych 8 šálků kávy, prosím."; console.log("Kolik šálků: " + text.match(//g)); // Jednodušší způsob pomocí zkratky \d console.log("Kolik šálků: " + text.match(/\d/g)); // Předá vše kromě čísel console.log(text.match(/\D/g));

// Fungovat bude pouze "kočka" a "can", nikoli "auto".

var text = "kočičí konzerva" ;

řídicí panel. log(text. shoda(/ca/g));

// Projde vše kromě kočky a plechovky (je tam symbol ^)

řídicí panel. log (text . shoda (/ca[^tn]/g ) ) ;

// Další příklad, kdy projdou pouze čísla

text = "Chtěl bych 8 šálků kávy, prosím.";

řídicí panel. log ("Kolik šálků: " + text . shoda (//g) ) ;

// Jednodušší způsob pomocí zkratky \d

řídicí panel. log("Kolik kelímků: " + text . shoda (/\d/g ) );

// Projde vše kromě čísel

řídicí panel. log(text. shoda(/\D/g));

Odpovídající slova

Ve většině případů je potřeba hledat celá slova, nikoli jednotlivé znaky. To se provádí pomocí modifikátorů (+) a (-), které opakují znak nebo sadu znaků.

Sčítání (X) udává přesný počet opakování, (x, y) – rozsah (x a y jsou čísla).

Navíc existuje speciální vzor \b, který odpovídá hranicím na koncích slov.

var text = "Ahoj lidé roku 1974. Přicházím z budoucnosti. V roce 2014 máme laserová děla, vznášedla a žijeme na Měsíci!"; // Najde roky. \d+ bude odpovídat jednomu nebo více znakům var yearRegex = /\d+/g; console.log("Roky: ", text.match(rokRegex)); // Najde všechny věty. Naše věty začínají velkým písmenem a končí tečkou nebo vykřičníkem. var větaRegex = /.+?(\.|!)/g; console.log("Sentences: ", text.match(sentenceRegex)); // Najde všechna slova začínající na "h". Vyhovují nám velká i malá písmena, proto k definici hranice slova používáme modifikátor i // \b. var hWords = /\bh\w+/ig; console.log("H Slova: ", text.match(hWords)); // Najde všechna slova od 4 do 6 znaků var findWords = /\b\w(4,6)\b/g; console.log("Slova mezi 4 a 6 znaky: ", text.match(findWords)); // Hledání slov delších než 5 znaků console.log("Slova 5 znaků nebo delší: ", text.match(/\b\w(5,)\b/g)); // Najde slova dlouhá přesně 6 znaků console.log("Slova přesně 6 znaků dlouhá: ", text.match(/\b\w(6)\b/g));

var text = "Ahoj lidé z roku 1974. Pocházím z budoucnosti. V roce 2014 máme laserová děla, vznášedla a žijeme na Měsíci!";

// Najde roky. \d+ odpovídá jednomu nebo více znakům

var yearRegex = /\d+/g ;

řídicí panel. log ( "Roky: " , text . shoda ( rokRegex ) ) ;

// Najde všechny věty. Naše věty začínají velkým písmenem a končí tečkou nebo vykřičníkem.

var větaRegex = /.+?(\.|!)/g ;

řídicí panel. log("Sentences: ", text. match(sentenceRegex));

// Najde všechna slova začínající na "h". Vyhovují nám velká i malá písmena, proto používáme modifikátor i

// \b k určení hranic slov.

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

řídicí panel. log ( "H Slova: " , text . shoda ( hWords ) );

// Najde všechna slova od 4 do 6 znaků

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

řídicí panel. log( "Slova mezi 4 a 6 znaky: ", text . match(findWords));

// Hledání slov delších než 5 znaků

řídicí panel. log ("Slova 5 znaků nebo delší: " , text . shoda (/\b\w(5,)\b/g ) ) ;

// Najděte slova dlouhá přesně 6 znaků

řídicí panel. log( "Slova přesně 6 znaků dlouhá: ", text . shoda (/\b\w(6)\b/g ) );

Ověření celého řetězce

V JavaScriptu lze takové výrazy použít k ověření uživatelského vstupu z textových polí. K ověření řetězců se používá regulární regulární výraz svázaný se začátkem a koncem textového fragmentu, přičemž se pro tento účel používají výrazy ^ (začátek řádku) a $ (konec řádku). Tyto symboly zajistí, že vzor, ​​který napíšete, bude pokrývat celou délku textu, a nikoli pouze jeho část.

V tomto případě navíc používáme metodu test() objektu regulárního výrazu, která při testování, zda regulární výraz odpovídá řetězci, vrací hodnotu true nebo false.

// Máme pole řetězců, pojďme najít odkazy..com/", "123461", "https://site/?s=google", "http://není platná url", "abc http: / /invalid.url/" ]; var regex = /^https?:\/\/[\w\/?.&-=]+$/; var urls = ; for(var i = 0; i< strings.length; i++){ if(regex.test(strings[i])){ // Валидная ссылка urls.push(strings[i]); } } console.log("Valid URLs: ", urls);

// Máme pole řetězců, pojďme najít odkazy.

var strings = [

"https://site/",

"toto není URL" ,

"https://google.com/",

"123461" ,

"https://site/?s=google" ,

"http://není platná adresa URL" ,

"abc http://invalid.url/"

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

var url = ;

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

if (regulární výraz . test (řetězce [ i ] ) ) (

adresy URL. push(strings[i]);

řídicí panel. log("Platné adresy URL: ", adresy URL);

Hledat a nahradit

Dalším běžným úkolem, který je usnadněn používáním regulárních výrazů, je hledání a nahrazování textu.

Téma regulárních výrazů je poměrně obsáhlé a nelze jej obsáhnout v jedné lekci, ale účelem našich lekcí je poskytnout vám základní pochopení jazyka javascript a jeho možností, proto není možné regulární výrazy ignorovat.

Nejprve pojďme zjistit, co to je.
Regulární výraz- toto je instrukce, která popisuje ve speciálně vyvinutém jazyce (RegExp) zákon „podobnosti“ požadovaného řetězce se vzorem.

K čemu to je? Například:

  • Uspořádat hledání něčeho v textu.
  • Nahrazení jedné části podřetězců jinými.
  • Chcete-li zkontrolovat správnost zadání uživatele (pravděpodobně jste se nejednou setkali se situací, kdy jste zadali svou e-mailovou adresu do nějakého formuláře a zobrazila se chyba jako "Neplatný e-mail").

Nebudeme zabíhat do podrobností, ale podívejme se, jak nastavit regulární výrazy. Existují dva způsoby, v této lekci se podíváme na jeden (tvorba v doslovném zápisu):

Var p=/pattern/flags;

Kde
vzor- vzor je základem regulárního výrazu, který definuje kritéria pro shodu řetězců. Skládá se z literálů a metaznaků.
vlajky- příznaky (modifikátory), specifikujte Extra možnosti shoda vzorů.

Var par=/+/i;

Tady + - šablona, ​​doslova znamená následující „libovolný počet čísel a písmen 1 nebo vícekrát“ (jak nastavit šablonu uvidíme níže).

i

Aby bylo jasnější, o čem mluvíme, podívejme se na příklad. Předpokládejme, že máme formulář, kam uživatel zadá svůj email a heslo. Chceme, aby se po kliknutí na tlačítko „Registrovat“ zkontrolovala správnost zadání.

Kód HTML stránky bude následující:

Regulární výrazy Javascriptu

Registrační formulář



Co by tedy funkce měla dělat? prov_address()? Pro začátek potřebujeme dvě proměnné, do kterých umístíme hodnoty zadané uživatelem:

funkce prov_adress(obj) ( var adr=obj.mail.value; var par=obj.pas.value; )

Nyní musíme nastavit vzory (regulární výrazy), se kterými budeme porovnávat, co uživatel zadal. Tady je dám, promluvíme si o tom, jak je skládat později:

funkce prov_adress(obj) ( var adr=obj.mail.value; var par=obj.pas.value; var adr_pattern=/+@+\.(2,5)/i; var par_pattern=/+/i; )

Nyní zkontrolujeme shodu vzorů. K tomu použijeme metodu test objekt RegExp:

function prov_adress(obj) ( var adr=obj.mail.value; var par=obj.pas.value; var adr_pattern=/+@+\.(2,5)/i; var par_pattern=/+/i; var prov=vzor_adr.test(adr) var prov1=vzor_par.test(par);

Čára adr_pattern.test(adr) znamená následující: kontrola existence v řetězci adr sekvence odpovídající regulárnímu výrazu adr_pattern. Metoda test vrátí booleovskou hodnotu (true nebo false).

Jediné, co musíme udělat, je v naší funkci uvést, co dělat v případě úspěšné (nebo neúspěšné) kontroly:

function prov_adress(obj) ( var adr=obj.mail.value; var par=obj.pas.value; var adr_pattern=/+@+\.(2,5)/i; var par_pattern=/+/i; var prov=adr_pattern.test(adr var prov1=par_pattern.test(par); if (prov==pravda && prov1==pravda) ( ​​alert("Jste zaregistrován!"); ) else ( alert("); Zadané údaje jsou nesprávné !"); ) )

Hotovo, doufám, že chápete podstatu toho, co děláme. Než ale zkontrolujeme fungování našeho skriptu, podívejme se, z čeho se naše regulární výrazy skládají.

Vezměme si regulární výraz pro naše heslo - /+/i:

  • /+/ - šablonu, ve které:
    • 0-9 - jakékoliv číslo.

    • a-z- libovolné malé písmeno od a do z.

    • - hranaté závorky znamenají, že vzor může obsahovat libovolný z literálů v nich uvedených (v našem případě čísla a malá písmena)

    • + - označuje, že tato část vzoru (tj. to, co je v hranatých závorkách) se může jednou nebo vícekrát opakovat.


  • i- příznak označující, že na velikosti písmen nezáleží.

Jinými slovy, náš regulární výraz určuje, že heslo může obsahovat libovolný počet číslic a písmen 1 nebo vícekrát (tj. může se skládat z jednoho čísla, jednoho písmene, mnoha číslic, mnoha písmen, číslic a písmen) .

Pokud například uživatel zadá do pole hesla „2“, „a3b“ nebo „leopard“, bude takové heslo považováno za správné. A pokud zadá „ab&s“ nebo „24?“, pak takové heslo nebude považováno za správné, protože obsahuje speciální znaky a my jsme je v regulárním výrazu nepovolili.

Doufám, že je nyní jasné, jak a proč můžete regulární výrazy používat, zbývá jen naučit se principy jejich skládání. Přísně vzato, úkol sestavit regulární výraz spočívá ve vytvoření jeho šablony. A šablona, ​​jak si pamatujete, se může skládat z literálů a metaznaků.

Začněme tím nejjednodušším - doslovy:

  • Každý z těchto symbolů představuje sám sebe. Například /abc/ - tomuto vzoru odpovídá pouze řetězec "abc".

  • a-z- všechna malá písmena od a do z. Například /a-z/ - tento vzor odpovídá 26 řetězcům: "a", "b", "c"... "z"

  • A-Z- Všechno velká písmena od A do Z.

  • 0-9 - všechna čísla.

Pokud chceme naznačit, že může existovat několik čísel nebo písmen, budeme muset použít řídicí znaky:
  • * - označuje, že znak (nebo část vzoru, pokud je uzavřen v hranatých závorkách) se může opakovat 0 nebo vícekrát. Například /ab*c/ - znamená, že řádek začíná znakem a, poté může být libovolný počet znaků b, následovaný znakem c. Tito. mohou to být například následující řetězce: "ac", "abc", "abbbbbbc" atd.

  • + - označuje, že znak (nebo část vzoru, je-li uzavřen v hranatých závorkách) lze opakovat 1 nebo vícekrát. Například /ab+c/ - znamená, že řádek začíná znakem a, poté může být libovolný počet znaků b (ale ne méně než 1), následovaný znakem c. Tito. mohou to být například následující řetězce: "abc", "abbbbbbc" atd.

  • . - označuje, že toto místo může obsahovat libovolný jednotlivý znak kromě znaku nového řádku. Například pro vzor /ab.c/ jsou srovnatelné následující řetězce: "ab6c", "abxc", "ab=c" atd.

  • ? - označuje, že znak (nebo část vzoru, pokud je uzavřen v hranatých závorkách) se může opakovat 0 nebo 1krát. Například /ab?c/ - znamená, že řádek začíná znakem a, poté může, ale nemusí být jeden znak b, následovaný znakem c. Tito. mohou to být následující řetězce: "ac", "abc"

  • (n)- označuje, že znak (nebo část vzoru, pokud je uzavřen v hranatých závorkách) se může opakovat přesně nkrát. Například /ab(3)c/ - znamená, že řádek začíná znakem a, pak jsou zde 3 znaky b, následované znakem c. Tito. to bude řetězec "abbbc".

  • (n,)- označuje, že znak (nebo část vzoru, pokud je uzavřen v hranatých závorkách) se může n nebo vícekrát opakovat. Například /ab(3,)c/ - znamená, že řádek začíná znakem a, pak jsou 3 nebo více znaků b, následuje znak c. Tito. mohou to být následující řetězce: "abbbc", "abbbbbbbc" atd.

  • (n, m)- označuje, že znak (nebo část vzoru, pokud je uzavřen v hranatých závorkách) se může opakovat n až mkrát. Například /ab(1,3)c/ - znamená, že řádek začíná znakem a, pak jsou zde 1 až 3 znaky b, následované znakem c. Tito. mohou to být následující řetězce: "abc", "abbc", "abbc".

  • - takový vzor je srovnatelný s jakýmkoliv jedním znakem, který patří do množiny definované v závorkách. Sada je určena výčtem nebo určením rozsahu. Vzor // může být například shodný s následujícími řetězci: "a", "b", "c".

  • [^] - takový vzor je srovnatelný s jakýmkoliv jednotlivým znakem, který nepatří do množiny definované v závorkách. Vzor /[^abc]/ může například odpovídat řetězcům: "f", "x", "Z", ale nemůže odpovídat řetězcům: "a", "b", "c".

  • ^ - označuje, že znaky jsou srovnatelné se začátkem řádku. Vzor /^abc/ může například odpovídat řetězcům: "abcd", "abcfh", ale nemůže odpovídat řetězcům: "dabc", "cbabc" atd.

  • $ - označuje, že znaky odpovídají konci řádku. Vzor /abc$/ může například odpovídat řetězcům: "dabc", "fhabc", ale nemůže odpovídat řetězcům: "abcd", "abccb" atd.

  • | - označuje několik alternativních vzorů. Například vzor /ab|c/ bude odpovídat následujícím řetězcům: "ab" a "c".

  • \ - slouží k úniku speciálních znaků, tzn. zpětné lomítko před znakem znamená, že by měl být interpretován jako speciální. Například:
    • \d- odpovídá libovolnému číslu od 0 do 9.

    • \D- vše se shoduje kromě čísla.

    • \s- odpovídá prostoru.

    • \S- odpovídá všemu kromě mezery.

    • \w- odpovídá písmenu, číslu nebo podtržítku.

    • \W- odpovídá všemu kromě písmene, číslice nebo podtržítka.


  • Například vzor /x\d\d/ bude odpovídat řetězcům: "x01", "x25" atd., ale nebude odpovídat řetězcům: "A15", "x0A"...

    Zpětné lomítko se také používá k vytvoření speciálního znakového doslovu. Pokud například potřebujeme najít řetězec "a*b", pak uvedeme následující vzor /a\*b/.

Pomocí výše uvedených literálů a metaznaků můžete vytvořit jakékoli vzory, které se vám líbí (předpokládejte regulární výrazy). Podívejme se například, co jsme napsali pro šablonu e-mailu v našem příkladu:

Var adr_pattern=/+@+\.(2,5)/i;

Zadali jsme tedy, že e-mailová adresa obsahuje číslice, písmena a podtržítka 1 nebo vícekrát, za nimi následuje znak @, pak čísla, písmena a podtržítka znovu 1krát nebo vícekrát a poté tečka následovaná písmeny 2 až 5krát. Zhruba takto vypadají e-mailové adresy.

Nyní, když víte, co jsme přesně specifikovali v ukázce, můžete zkontrolovat fungování příkladu:

Někteří lidé, když se setkají s problémem, si pomyslí: "Ach, použiji regulární výrazy." Nyní mají dva problémy.
Jamie Zawinski

Yuan-Ma řekl: „Na řezání dřeva přes vlákno dřeva je potřeba hodně síly. Programování napříč strukturou problému vyžaduje hodně kódu.
Mistr Yuan-Ma, „Kniha programování“

Programovací nástroje a techniky přežívají a šíří se chaotickým evolučním způsobem. Někdy nepřežijí krásní a brilantní, ale prostě ti, kteří ve svém oboru fungují dostatečně dobře – například pokud jsou integrováni do jiné úspěšné technologie.

V této kapitole si probereme takový nástroj – regulární výrazy. Toto je způsob, jak popsat vzory v řetězcových datech. Vytvářejí malý, samostatný jazyk, který je součástí JavaScriptu a mnoha dalších jazyků a nástrojů.

Pravidelné jízdní řády jsou velmi zvláštní a velmi užitečné. Jejich syntaxe je tajemná a jejich programovací rozhraní JavaScriptu je neohrabané. Ale toto Výkonný nástroj pro zkoumání a zpracování řetězců. Jakmile je pochopíte, stanete se efektivnějšími programátory.

Vytvoření regulárního výrazu

Regular – typ objektu. Lze ji vytvořit voláním konstruktoru RegExp nebo napsáním požadované šablony ohraničené lomítky.

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

Oba tyto regulární výrazy představují stejný vzor: znak „a“ následovaný znakem „b“ následovaný znakem „c“.

Pokud použijete konstruktor RegExp, pak se vzor zapíše jako běžný řetězec, takže platí všechna pravidla týkající se zpětných lomítek.

Druhá položka, kde je vzor mezi lomítky, zachází se zpětnými lomítky odlišně. Za prvé, protože vzor končí lomítkem, musíte dát obrácené lomítko před lomítkem, které chceme zahrnout do našeho vzoru. Navíc zpětná lomítka, která nejsou součástí speciálních znaků, jako je \n, budou zachována (spíše než ignorována jako v řetězcích) a změní význam vzoru. Některé znaky, jako je otazník nebo plus, mají v regulárních výrazech speciální význam, a pokud takový znak potřebujete najít, musí mu předcházet i zpětné lomítko.

Var osmnáctPlus = /osmnáct\+/;

Abyste věděli, kterým znakům musí předcházet lomítko, musíte se naučit seznam všech speciálních znaků v regulárních výrazech. To zatím není možné, takže v případě pochybností stačí dát zpětné lomítko před jakýkoli znak, který není písmenem, číslem nebo mezerou.

Kontrola shod

Pravidelní mají několik metod. Nejjednodušší je test. Pokud mu předáte řetězec, vrátí booleovskou hodnotu označující, zda řetězec obsahuje výskyt daného vzoru.

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

Pravidelná sekvence skládající se pouze z nespeciálních znaků je jednoduše sekvencí těchto znaků. Pokud je abc kdekoli v řádku, který testujeme (nejen na začátku), test vrátí hodnotu true.

Hledá se soubor postav

Zda řetězec obsahuje abc, můžete také zjistit pomocí indexOf. Pravidelné vzory umožňují jít dále a vytvářet složitější vzory.

Řekněme, že potřebujeme najít nějaké číslo. Když do regulárního výrazu vložíme množinu znaků do hranatých závorek, znamená to, že tato část výrazu odpovídá libovolnému ze znaků v závorce.

Oba výrazy jsou v řádcích obsahujících číslo.

Console.log(//.test("v roce 1992")); // → true console.log(//.test("v roce 1992")); // → pravda

V hranatých závorkách se pomlčka mezi dvěma znaky používá k určení rozsahu znaků, kde je zadaná sekvence Unicode kódování. Znaky od 0 do 9 jsou tam jen za sebou (kódy od 48 do 57), takže je zachytí všechny a shoduje se s libovolným číslem.

Několik skupin znaků má své vlastní vestavěné zkratky.

\d Libovolné číslo
\w Alfanumerický znak
\s Znak mezery (mezera, tabulátor, nový řádek atd.)
\D není číslo
\W není alfanumerický znak
\S není znak mezery
. libovolný znak kromě odřádkování

Můžete tedy nastavit formát data a času jako 01/30/2003 15:20 s následujícím výrazem:

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")); // → nepravda

Vypadá to hrozně, že? Je zde příliš mnoho zpětných lomítek, což ztěžuje pochopení vzoru. Později to trochu vylepšíme.

V hranatých závorkách lze také použít zpětná lomítka. Například [\d.] znamená libovolné číslo nebo tečku. Všimněte si, že tečka uvnitř hranatých závorek ztrácí svůj zvláštní význam a stává se jednoduše tečkou. Totéž platí pro další speciální znaky, jako je +.

Sadu znaků můžete invertovat - to znamená, že potřebujete najít jakýkoli znak kromě těch, které jsou v sadě - umístěním znaménka ^ bezprostředně za úvodní hranatou závorku.

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

Opakující se části šablony

Víme, jak najít jedno číslo. Co když potřebujeme najít celé číslo – posloupnost jedné nebo více číslic?

Pokud za něco v pravidelném pořadí vložíte znaménko +, bude to znamenat, že tento prvek lze opakovat více než jednou. /\d+/ znamená jednu nebo více číslic.

Console.log(/"\d+"/.test(""123"")); // → true console.log(/"\d+"/.test("""")); // → false console.log(/"\d*"/.test(""123"")); // → true console.log(/"\d*"/.test("""")); // → pravda

Hvězdička * má téměř stejný význam, ale umožňuje, aby se vzor vyskytoval nulakrát. Pokud za něčím následuje hvězdička, pak to nikdy nebrání tomu, aby byl vzor v řádku – jen se tam objeví nulakrát.

Otazník činí část vzoru volitelnou, což znamená, že se může objevit nula nebo jednou. V následujícím příkladu se může objevit znak u, ale vzor se shoduje, i když tomu tak není.

Var soused = /soused?r/; console.log(neighbor.test("soused")); // → true console.log(neighbor.test("neighbor")); // → pravda

Složené závorky se používají k určení přesného počtu opakování vzoru. (4) za prvkem znamená, že se musí v řádku objevit 4krát. Můžete také zadat mezeru: (2,4) znamená, že prvek se musí vyskytnout alespoň 2krát a ne více než 4krát.

Další verze formátu data a času, kde jsou povoleny dny, měsíce a hodiny o jedné nebo dvou číslicích. A také je o něco čitelnější.

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

Můžete použít mezery s otevřeným koncem vynecháním jednoho z čísel. (,5,) znamená, že vzor se může vyskytnout od nuly do pětikrát, a (5,) znamená od pěti nebo více.

Seskupování podvýrazů

Chcete-li použít operátory * nebo + na více prvcích najednou, můžete použít závorky. Část regulárního výrazu uzavřená v závorkách je z pohledu operátorů považována za jeden prvek.

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

První a druhé plus platí pouze pro druhé o ve slovech boo a hoo. Třetí + odkazuje na celou skupinu(hoo+), nalezení jedné nebo více takových sekvencí.

Písmeno i na konci výrazu způsobuje, že regulární výraz nerozlišuje velká a malá písmena – takže B odpovídá b.

Zápasy a skupiny

Testovací metoda je nejjednodušší metodou pro kontrolu regulárních výrazů. Pouze vám řekne, zda byla nalezena shoda nebo ne. Regulari mají také metodu exec, která vrátí null, pokud nebylo nic nalezeno, a jinak vrátí objekt s informací o shodě.

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

Objekt vrácený exec has vlastnost indexu, který obsahuje číslo postavy, ze které došlo ke shodě. Obecně objekt vypadá jako pole řetězců, kde prvním prvkem je řetězec, u kterého byla zkontrolována shoda. V našem příkladu to bude posloupnost čísel, kterou jsme hledali.

Řetězce mají metodu shody, která funguje v podstatě stejným způsobem.

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

Pokud regulární výraz obsahuje podvýrazy seskupené v závorkách, objeví se v poli také text, který odpovídá těmto skupinám. Prvním prvkem je vždy úplná shoda. Druhá je část, která se shodovala s první skupinou (ta, jejíž závorky se vyskytly jako první), pak s druhou skupinou a tak dále.

Var quotedText = /"([^"]*)"/; console.log(quotedText.exec("řekla "ahoj"")); // → [""ahoj"", "ahoj"]

Pokud skupina není vůbec nalezena (například pokud za ní následuje otazník), její pozice v poli není definována. Pokud se skupina shoduje několikrát, bude v poli pouze poslední zápas.

Console.log(/bad(ly)?/.exec("špatný")); // → ["špatný", nedefinováno] console.log(/(\d)+/.exec("123")); // → ["123", "3"]

Skupiny jsou užitečné pro získávání částí řetězců. Pokud nechceme jen kontrolovat, zda má řetězec datum, ale extrahovat jej a vytvořit objekt reprezentující datum, můžeme posloupnosti čísel uzavřít do závorek a datum vybrat z výsledku exec.

Nejprve ale malá odbočka, ve které se naučíme preferovaný způsob ukládání data a času v JavaScriptu.

Typ data

JavaScript má standardní typ objekt pro data - nebo spíše okamžiky v čase. Jmenuje se Date. Pokud jednoduše vytvoříte objekt data přes nový, dostanete dnešní datum a čas.

Console.log(new Date()); // → Ne 9. listopadu 2014 00:07:57 GMT+0300 (CET)

Můžete také vytvořit objekt obsahující daný čas

Console.log(nové datum(2015, 9, 21)); // → St Oct 21 2015 00:00:00 GMT+0300 (CET) console.log(new Date(2009, 11, 9, 12, 59, 59, 999)); // → St. prosince 09 2009 12:59:59 GMT+0300 (CET)

JavaScript používá konvenci, kdy čísla měsíců začínají nulou a čísla dnů začínají jedničkou. To je hloupé a směšné. Dávej si pozor.

Poslední čtyři argumenty (hodiny, minuty, sekundy a milisekundy) jsou volitelné a pokud chybí, jsou nastaveny na nulu.

Časová razítka jsou uložena jako počet milisekund, které uplynuly od začátku roku 1970. Pro doby před rokem 1970 se používají záporná čísla (je to kvůli časové konvenci Unixu, která byla vytvořena v této době). Metoda getTime objektu data vrací toto číslo. Je přirozeně velký.
console.log(new Date(2013, 11, 19).getTime()); // → 1387407600000 console.log(new Date(1387407600000)); // → Čt 19. prosince 2013 00:00:00 GMT+0100 (CET)

Pokud dáte konstruktoru Date jeden argument, bude se s ním zacházet jako s tímto počtem milisekund. Aktuální hodnotu milisekund můžete získat vytvořením objektu Date a voláním metody getTime nebo voláním funkce Date.now.

Objekt Date má metody getFullYear, getMonth, getDate, getHours, getMinutes a getSeconds pro načtení jeho součástí. Existuje také metoda getYear, která vrací poměrně zbytečný dvoumístný kód jako 93 nebo 14.

Uzavřením příslušných částí šablony do závorek můžeme přímo z řetězce vytvořit objekt data.

Funkce findDate(string) ( var dateTime = /(\d(1,2))-(\d(1,2))-(\d(4))/; var match = dateTime.exec(string); return new Datum(číslo(shoda), Číslo(shoda) - 1, Číslo(shoda) ) console.log(findDate("30-1-2003")); // → Čt 30. ledna 2003 00:00:00 GMT+0100 (CET)

Hranice slov a řádků

Bohužel findDate stejně šťastně vydoluje nesmyslné datum 00-1-3000 z řetězce "100-1-30000". Shoda může nastat kdekoli v řetězci, takže v tomto případě bude jednoduše začínat na druhém znaku a končit na předposledním znaku.

Pokud potřebujeme vynutit shodu, aby zabrala celý řetězec, použijeme značky ^ a $. ^ odpovídá začátku řádku a $ odpovídá konci. Proto /^\d+$/ odpovídá řetězci obsahujícímu pouze jednu nebo více číslic, /^!/ odpovídá řetězci začínajícímu vykřičníkem a /x^/ neodpovídá žádnému řetězci (nesmí být x).

Pokud se naopak chceme ujistit, že datum začíná a končí na hranici slova, použijeme značku \b. Hranicí slova může být začátek nebo konec řádku nebo jakékoli místo v řádku, kde je na jedné straně alfanumerický znak \w a na druhé nealfanumerický znak.

Console.log(/cat/.test("concatenate")); // → true console.log(/\bcat\b/.test("concatenate")); // → nepravda

Všimněte si, že štítek hranice není symbol. Je to prostě omezení, což znamená, že ke shodě dojde pouze v případě, že je splněna určitá podmínka.

Šablony s možností výběru

Řekněme, že potřebujete zjistit, zda text neobsahuje pouze číslo, ale číslo, za kterým následuje prase, kráva nebo kuře v jednotném nebo množném čísle.

Bylo by možné napsat tři regulární výrazy a zkontrolovat je jeden po druhém, ale existuje lepší způsob. Symbol | označuje výběr mezi vzory nalevo a napravo od něj. A můžeme říci následující:

Var počet zvířat = /\b\d+ (prase|kráva|kuře)s?\b/; console.log(animalCount.test("15 prasat")); // → true console.log(animalCount.test("15 prasátek")); // → nepravda

Závorky vymezují část vzoru, na kterou se vztahuje |, a mnoho takových operátorů lze umístit jeden za druhým, aby indikovaly výběr z více než dvou možností.

Vyhledávač

Regulární výrazy lze chápat jako vývojové diagramy. Následující diagram popisuje nedávný příklad dobytka.

Výraz odpovídá řetězci, pokud je možné najít cestu z levé strany diagramu doprava. Pamatujeme si aktuální pozici v řádku a pokaždé, když procházíme obdélníkem, kontrolujeme, zda část úsečky bezprostředně za naší pozicí v něm odpovídá obsahu obdélníku.

To znamená, že kontrola, zda se náš běžný znak shoduje s řetězcem „3 prasata“ při procházení vývojovým diagramem, vypadá takto:

Na pozici 4 je hranice slova a míjíme první obdélník
- od 4. pozice najdeme číslo a projdeme druhým obdélníkem
- na pozici 5 se jedna cesta uzavírá zpět před druhý obdélník a druhá jde dále k obdélníku s mezerou. Máme mezeru, ne číslo a volíme druhou cestu.
- nyní jsme na pozici 6, začátku „prasat“ a na trojitém rozvětvení cest. V řadě není žádná „kráva“ ani „kuře“, ale „prase“, takže volíme tuto cestu.
- na pozici 9 za trojitým rozvětvením jedna cesta obchází „s“ a jde do posledního hraničního obdélníku slova a druhá prochází „s“. Máme "s", takže jdeme tam.
- na pozici 10 jsme na konci řádku a může se shodovat pouze hranice slova. Konec úsečky je považován za hranici a procházíme posledním obdélníkem. A nyní jsme úspěšně našli naši šablonu.

Regulární výrazy v podstatě fungují tak, že algoritmus začíná na začátku řetězce a snaží se tam najít shodu. V našem případě je tam hranice slova, takže projde prvním obdélníkem - ale není tam žádné číslo, takže narazí na druhý obdélník. Pak se přesune na druhý znak v řetězci a pokusí se tam najít shodu... A tak dále, dokud nenajde shodu nebo se nedostane na konec řetězce, v takovém případě není nalezena žádná shoda.

Zpětné provize

Regulární výraz /\b(+b|\d+|[\da-f]h)\b/ odpovídá buď binárnímu číslu následovanému ab, desítkovému číslu bez přípony nebo hexadecimálnímu číslu (čísla 0 až 9 nebo symboly od a do h), následované h. Příslušný diagram:

Při hledání shody se může stát, že algoritmus zvolí horní cestu (binární číslo), i když takové číslo v řetězci není. Pokud je tam například řádek „103“, je jasné, že až po dosažení čísla 3 algoritmus pochopí, že je na špatné cestě. Obecně platí, že řádek odpovídá pravidelné sekvenci, jen ne v tomto vláknu.

Poté se algoritmus vrátí zpět. Na rozcestí si pamatuje aktuální pozici (v našem případě je to začátek řádku hned za slovem hranice), abyste se mohli vrátit a zkusit jinou cestu, pokud zvolená nefunguje. U řetězce „103“ se po setkání s trojkou vrátí zpět a pokusí se projít desetinnou cestu. To bude fungovat, takže bude nalezena shoda.

Algoritmus se zastaví, jakmile nalezne úplnou shodu. To znamená, že i když může být vhodných několik možností, použije se pouze jedna z nich (v pořadí, v jakém se objevují v pravidelném pořadí).

Zpětné sledování nastává při použití operátorů opakování, jako jsou + a *. Pokud hledáte /^.*x/ v řetězci "abcxe", část regulárního výrazu.* se pokusí spotřebovat celý řetězec. Algoritmus si pak uvědomí, že potřebuje také „x“. Protože za koncem řetězce není žádné „x“, algoritmus se pokusí vyhledat shodu posunutím o jeden znak zpět. Po abcx také není x, pak se to vrátí zpět, tentokrát na podřetězec abc. A po řádku najde x a oznámí úspěšnou shodu, na pozicích 0 až 4.

Můžete napsat pravidelnou rutinu, která povede k několika vrácením zpět. K tomuto problému dochází, když se vzor může vícekrát shodovat se vstupními daty. v různých cestách. Například když uděláme chybu při psaní regulárního výrazu pro binární čísla, můžeme omylem napsat něco jako /(+)+b/.

Pokud by algoritmus hledal takový vzor v dlouhém řetězci 0s a 1s, který by neměl na konci „b“, prošel by nejprve vnitřní smyčkou, dokud by mu nedošly číslice. Pak si všimne, že na konci není žádné „b“, vrátí se o jednu pozici zpět, projde vnější smyčkou, znovu to vzdá, pokusí se převrátit zpět do jiné polohy po vnitřní smyčce... A bude pokračovat vyhledávat tímto způsobem pomocí obou smyček. To znamená, že množství práce s každým znakem řádku se zdvojnásobí. I pro několik desítek postav bude hledání shody trvat velmi dlouho.

nahradit metoda

Řetězce mají metodu nahrazení, která může nahradit část řetězce jiným řetězcem.

Console.log("táta".replace("p", "m")); // → mapa

První argument může být také regulární výraz, v takovém případě je nahrazen první výskyt regulárního výrazu v řádku. Když je k regulárnímu výrazu přidána možnost „g“ (globální), budou nahrazeny všechny výskyty, nejen první

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

Mělo by smysl předat možnost „nahradit vše“ samostatným argumentem nebo samostatnou metodou, jako je nahradit vše. Ale bohužel se tato možnost přenáší prostřednictvím samotného běžného systému.

Plná síla regulárních výrazů se projeví, když použijeme odkazy na skupiny nalezené v řetězci specifikovaném v regulárním výrazu. Máme například řádek obsahující jména lidí, jedno jméno na řádek, ve formátu „Příjmení, Jméno“. Pokud je potřebujeme prohodit a odstranit čárku, abychom získali „First Name Last Name“, napíšeme následující:

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

$1 a $2 v náhradním řádku odkazují na skupiny znaků v závorkách. $1 se nahradí textem, který odpovídá první skupině, $2 druhou skupinou atd., až do výše $9. Celá shoda je obsažena v proměnné $&.

Jako druhý argument můžete také předat funkci. Pro každou náhradu bude zavolána funkce, jejíž argumenty budou nalezené skupiny (a celá odpovídající část řádku), a její výsledek bude vložen do nového řádku.

Jednoduchý příklad:

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

Zde je jeden zajímavější:

Var stock = "1 citron, 2 zelí a 101 vajec"; funkce minusJedna(shoda, množství, jednotka) ( množství = Číslo(částka) - 1; jestliže (částka == 1) // zbývá pouze jedno, odstraňte "s" na konci unit = unit.slice(0, unit. délka - 1 else if (částka == 0) částka = "ne"; vrácená částka + " " + jednotka ) console.log(stock.replace(/(\d+) (\w+)/g, minusJedna) ); // → žádný citron, 1 zelí a 100 vajec

Kód vezme řetězec, najde všechny výskyty čísel následovaných slovem a vrátí řetězec s každým číslem zmenšeným o jednu.

Skupina (\d+) přejde do argumentu množství a (\w+) přejde do argumentu jednotky. Funkce převede částku na číslo - a to vždy funguje, protože náš vzor je \d+. A pak provede změny slova, v případě, že zbývá pouze 1 položka.

Chamtivost

Je snadné použít nahradit k napsání funkce, která odstraní všechny komentáře JavaScript kód. Zde je první pokus:

Funkce stripComments(code) ( return code.replace(/\/\/.*|\/\*[^]*\*\//g, ""); ) console.log(stripComments("1 + /*) 2 */3")); // → 1 + 3 console.log(stripComments("x = 10;// deset!")); // → x = 10; console.log(stripComments("1 /* a */+/* b */ 1")); // → 11

Část před operátorem "or" odpovídá dvěma lomítkům následovaným libovolným počtem znaků kromě nových řádků. Část, která odstraňuje víceřádkové komentáře, je složitější. Používáme [^], tzn. jakýkoli znak, který není prázdný, jako způsob, jak najít jakýkoli znak. Nemůžeme použít tečku, protože komentáře bloku pokračují na novém řádku a znak nového řádku neodpovídá tečce.

Ale výstup předchozího příkladu je nesprávný. Proč?

Část [^]* se nejprve pokusí zachytit co nejvíce postav. Pokud kvůli tomu další část pravidelné sekvence nenajde shodu, vrátí se o jeden znak zpět a zkusí to znovu. V tomto příkladu se algoritmus pokusí zachytit celý řádek a poté se vrátí zpět. Po vrácení 4 znaků zpět najde v řádku */ - a to jsme nechtěli. Chtěli jsme zachytit pouze jeden komentář a ne jít na konec řádku a najít poslední komentář.

Z tohoto důvodu říkáme, že operátory opakování (+, *, ? a ()) jsou nenasytné, což znamená, že nejprve chytnou, co mohou, a pak se vrátí zpět. Pokud položíte otázku po operátorovi jako je tento (+?, *?, ??, ()?), změní se na nenažrané a začnou hledat nejmenší možné výskyty.

A to je to, co potřebujeme. Tím, že hvězdičku přinutíme najít shodu v minimálním možném počtu znaků v řádku, spotřebujeme pouze jeden blok komentářů a nic víc.

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

Mnoho chyb se vyskytuje při použití chamtivých operátorů místo těch, které nejsou chamtivé. Při použití operátoru opakování vždy nejprve zvažte operátor, který není chamtivý.

Dynamické vytváření objektů RegExp

V některých případech není v době psaní kódu znám přesný vzor. Například budete muset v textu vyhledat jméno uživatele a uzavřít ho podtržítky. Vzhledem k tomu, že jméno budete znát až po spuštění programu, nemůžete použít lomítko.

Ale můžete vytvořit řetězec a použít konstruktor RegExp. Zde je příklad:

Jméno var = "harry"; var text = "A Harry má na čele jizvu."; var regexp = new RegExp("\\b(" + jméno + ")\\b", "gi"); console.log(text.replace(regexp, "_$1_")); // → A _Harry_ má na čele jizvu.

Při vytváření hranic slov musíme používat dvojitá lomítka, protože je píšeme na normálním řádku, a ne v pravidelném pořadí s dopřednými lomítky. Druhý argument k RegExp obsahuje možnosti pro regulární výrazy - v našem případě „gi“, tj. globální a nerozlišuje malá a velká písmena.

Ale co když je jméno „dea+hlrd“ (pokud je náš uživatel kulhatzker)? Ve výsledku dostaneme nesmyslný regulární výraz, který v řetězci nenajde shody.

Před jakoukoli postavu, která se nám nelíbí, můžeme přidat zpětná lomítka. Před písmena nemůžeme přidávat zpětná lomítka, protože \b nebo \n jsou speciální znaky. Ale můžete bez problémů přidat lomítka před jakékoli nealfanumerické znaky.

Název var = "dea+hlrd"; var text = "Tento dea+hlrd obtěžuje každého."; var escaped = name.replace(/[^\w\s]/g, "\\$&"); var regexp = new RegExp("\\b(" + escaped + ")\\b", "gi"); console.log(text.replace(regexp, "_$1_")); // → Tohle _dea+hlrd_ všechny naštvalo.

metoda vyhledávání

Metodu indexOf nelze použít s regulárními výrazy. Existuje však metoda vyhledávání, která pouze očekává regulární výraz. Stejně jako indexOf vrací index prvního výskytu nebo -1, pokud se žádný nevyskytuje.

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

Bohužel neexistuje způsob, jak říci metodě, aby hledala shodu začínající na určitém offsetu (jak to můžete udělat s indexOf). To by bylo užitečné.

vlastnost lastIndex

Metoda exec také nefunguje pohodlný způsob začněte hledat od dané pozice v řetězci. Ale dává to nepohodlný způsob.

Objekt regulárního výrazu má vlastnosti. Jedním z nich je source, který obsahuje řetězec. Dalším je lastIndex, který za určitých podmínek řídí, kde začne další hledání výskytů.

Mezi tyto podmínky patří, že musí být přítomna globální volba g a že vyhledávání musí být provedeno pomocí metody exec. Rozumnějším řešením by bylo jednoduše povolit předání zvláštního argumentu exec, ale rozumnost není základním rysem rozhraní regulárního výrazu JavaScriptu.

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

Pokud je hledání úspěšné, volání exec aktualizuje vlastnost lastIndex tak, aby ukazovala na pozici za nalezeným výskytem. Pokud nedošlo k úspěchu, lastIndex se nastaví na nulu – stejně jako lastIndex nově vytvořeného objektu.

Při použití globální regulární proměnné a více volání exec, tyto automatické aktualizace lastIndex může způsobit problémy. Váš běžný server může začít hledat od pozice, která zůstala po předchozím hovoru.

Var číslice = /\d/g; console.log(digit.exec("tady to je: 1")); // → ["1"] console.log(digit.exec("a teď: 1")); // → null

Dalším zajímavým efektem volby g je to, že mění způsob, jakým metoda shody funguje. Při volání s touto volbou místo vracení pole jako výsledek exec najde všechny výskyty vzoru v řetězci a vrátí pole nalezených podřetězců.

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

Buďte tedy opatrní s globálními regulárními proměnnými. Případy, kdy jsou potřeba – nahraďte hovory nebo místa, kde konkrétně používáte lastIndex – jsou pravděpodobně všechny případy, ve kterých by se měly používat.

Cykly výskytu

Typickým úkolem je iterovat všechny výskyty vzoru v řetězci, aby měl přístup k objektu shody v těle smyčky pomocí lastIndex a exec.

Var input = "Řádek se 3 čísly... 42 a 88."; číslo var = /\b(\d+)\b/g; var zápas; while (match = číslo.exec(vstup)) console.log("Nalezeno ", shoda, " na ", shoda.index); // → Nalezeno 3 od 14 // Nalezeno 42 od 33 // Nalezeno 88 od 40

Využívá toho, že hodnotou přiřazení je hodnota, která se přiřazuje. Použitím match = re.exec(input) jako podmínky v cyklu while hledáme na začátku každé iterace, uložíme výsledek do proměnné a cyklus ukončíme, když jsou nalezeny všechny shody.

Analýza INI souborů

Na závěr kapitoly se podívejme na problém s použitím regulárních výrazů. Představte si, že píšeme program, který sbírá informace o našich nepřátelích přes internet. automatický režim. (Nebudeme psát celý program, jen část, která čte soubor nastavení. Omlouváme se.) Soubor vypadá takto:

Searchengine=http://www.google.com/search?q=$1 zlomyslnost=9.7 ; před komentáře je umístěn středník; každá sekce odkazuje na jiného nepřítele celé jméno=Larry Doe typ=kindergarten bull website=http://www.geocities.com/CapeCanaveral/11451 fullname=Gargamel type=evil wizard outputdir=/home/marijn/enemies/gargamel

Přesný formát souboru (který je poměrně široce používaný a obvykle se nazývá INI) je následující:

Prázdné řádky a řádky začínající středníkem jsou ignorovány
- řádky v hranatých závorkách začínají nová sekce
- řádky obsahující alfanumerický identifikátor následovaný = přidat nastavení v této části

Vše ostatní jsou nesprávná data.

Naším úkolem je převést takový řetězec na pole objektů, z nichž každý má vlastnost name a pole nastavení. Jeden objekt je potřeba pro každou sekci a další je potřeba pro globální nastavení nad souborem.

Protože je třeba soubor analyzovat řádek po řádku, je dobré začít rozdělením souboru na řádky. K tomu jsme použili string.split("\n") v kapitole 6. Některé operační systémy nepoužívají pro zalomení řádku jeden znak \n, ale dva - \r\n. Protože metoda rozdělení bere jako argument regulární výrazy, můžeme rozdělit řádky pomocí výrazu /\r?\n/, což umožňuje jak jednotlivé \n, tak \r\n mezi řádky.

Funkce parseINI(string) ( // Začněme objektem obsahujícím nastavení nejvyšší úrovně var currentSection = (název: null, pole: ); var category = ; string.split(/\r?\n/).forEach(function (line ) ( var match; if (/^\s*(;.*)?$/.test(line)) ( return; ) else if (match = line.match(/^\[(.*)\ ]$ /)) ( currentSection = (název: shoda, pole: ); category.push (currentSection); ) else if (match = line.match(/^(\w+)=(.*)$/)) ( aktuálníSekce.push((název: shoda, hodnota: shoda) else ( throw new Error("Řádek "" + řádek + "" obsahuje neplatná data."); ) ));

Kód prochází všemi řádky a aktualizuje objekt aktuální sekce „aktuální sekce“. Nejprve zkontroluje, zda lze řádek ignorovat pomocí regulárního výrazu /^\s*(;.*)?$/. Dokážete si představit, jak to funguje? Část mezi závorkami odpovídá komentářům, co? dělá to tak, že běžný znak bude odpovídat také řádkům obsahujícím pouze mezery.

Pokud řádek není komentářem, kód zkontroluje, zda nezačíná novou sekci. Pokud ano, vytvoří se nový objekt pro aktuální sekci, ke kterému se přidají další nastavení.

Poslední smysluplnou možností je, že řetězec je normální nastavení, v takovém případě se přidá k aktuálnímu objektu.

Pokud nefunguje žádná z možností, funkce vyvolá chybu.

Všimněte si, jak časté používání ^ a $ zajišťuje, že výraz odpovídá celému řetězci, nikoli jen jeho části. Pokud je nepoužíváte, kód bude obecně fungovat, ale někdy bude produkovat podivné výsledky a chybu bude obtížné vystopovat.

Konstrukce if (match = string.match(...)) je podobná triku s použitím přiřazení jako podmínky v cyklu while. Často nevíte, že volání shody bude úspěšné, takže k výslednému objektu můžete přistupovat pouze uvnitř bloku if, který jej kontroluje. Abychom nenarušili krásný řetězec if kontrol, přiřadíme výsledek hledání k proměnné a toto přiřazení rovnou použijeme jako kontrolu.

Mezinárodní symboly

Vzhledem k původně jednoduché implementaci jazyka a následnému zafixování takové implementace „v žule“ jsou pravidelní JavaScript hloupí se znaky, které se nenacházejí v anglický jazyk. Například znak „písmeno“ může být z pohledu regulárních výrazů JavaScriptu jedním z 26 písmen anglické abecedy a z nějakého důvodu také podtržítko. Písmena jako é nebo β, která jsou jasně písmena, se neshodují s \w (a budou odpovídat \W, což je nepísmeno).

V podivném zvratu historicky \s (mezera) odpovídá všem znakům, které jsou v Unicode považovány za mezery, včetně věcí, jako je nerozdělitelná mezera nebo mongolský oddělovač samohlásek.

Některé implementace regulárních výrazů v jiných jazycích mají speciální syntaxi pro vyhledávání speciálních kategorií znaků Unicode, jako je „všechny velká písmena", "všechna interpunkce" nebo "řídicí znaky". Existují plány na přidání takových kategorií do JavaScriptu, ale pravděpodobně nebudou brzy implementovány.

Sečteno a podtrženo

Reguláry jsou objekty, které představují vyhledávací vzory v řetězcích. K vyjádření těchto vzorů používají vlastní syntaxi.

/abc/ Posloupnost znaků
// Libovolný znak ze seznamu
/[^abc]/ Libovolný znak kromě znaků ze seznamu
// Libovolný znak z intervalu
/x+/ Jeden nebo více výskytů vzoru x
/x+?/ Jeden nebo více výskytů, nezištný
/x*/ Žádný nebo více výskytů
/x?/ Nula nebo jeden výskyt
/x(2,4)/ Od dvou do čtyř výskytů
/(abc)/ Skupina
/a|b|c/ Jakýkoli z několika vzorů
/\d/ Libovolné číslo
/\w/ Libovolný alfanumerický znak („písmeno“)
/\s/ Libovolný znak mezery
/./ Libovolný znak kromě zalomení řádků
/\b/ Hranice slova
/^/ Začátek řádku
/$/ Konec řádku

Regulární výraz má testovací metodu pro kontrolu, zda je vzor v řetězci. Existuje metoda exec, která vrací pole obsahující všechny nalezené skupiny. Pole má vlastnost index, která obsahuje číslo znaku, ze kterého došlo ke shodě.

Řetězce mají metodu shody pro shodu vzorků a metodu vyhledávání, která vrací pouze počáteční pozici výskytu. Metoda nahrazení může nahradit výskyty vzoru jiným řetězcem. Kromě toho můžete předat funkci k nahrazení, která vytvoří náhradní řádek na základě šablony a nalezených skupin.

Regulární znaky mají nastavení, která se zapisují za koncové lomítko. Volba i nerozlišuje velká a malá písmena regulárního výrazu a volba g jej činí globálním, což mimo jiné způsobí, že metoda nahradit nahradí všechny nalezené výskyty, nejen ten první.

Konstruktor RegExp lze použít k vytvoření regulárních výrazů z řetězců.

Regulátory jsou ostrý nástroj s nepohodlnou rukojetí. Některé úkoly značně zjednodušují a při řešení jiných, složitých problémů se mohou stát nezvládnutelnými. Součástí učení se používat regulární výrazy je umět odolat pokušení nacpat do nich úkol, pro který nejsou určeny.

Cvičení

Nevyhnutelně se při řešení problémů setkáte s nepochopitelnými případy a možná si někdy budete zoufat, když uvidíte nepředvídatelné chování některých regulárních výrazů. Někdy pomůže nastudovat chování běžného motoru prostřednictvím online služby, jako je debuggex.com, kde můžete vidět jeho vizualizaci a porovnat ji s požadovaným efektem.
Pravidelný golf
„Golf“ v kódu je hra, kde se potřebujete vyjádřit daný program minimální počet znaků. Pravidelný golf je praktickým cvičením psaní co nejmenších štamgastů k nalezení daného vzoru, a to jedině.

Pro každý z podřádků napište regulární výraz, abyste zkontrolovali jejich umístění v řádku. Běžný stroj by měl najít pouze tyto zadané podřetězce. Nedělejte si starosti s hranicemi slov, pokud to není výslovně uvedeno. Když máte fungující pravidelný vzor, ​​zkuste jej snížit.

Auto a kočka
- pop a rekvizita
- fretka, trajekt a ferrari
- Jakékoli slovo končící na ious
- Mezera následovaná tečkou, čárkou, dvojtečkou nebo středníkem.
- Slovo delší než šest písmen
- Slovo bez písmen e

// Zadejte své regulární výrazy ověřit(/.../, ["moje auto", "zlé kočky"], ["camper", "vysoké umění"]); ověřit(/.../, ["popkultura", "šílené rekvizity"], ["plop"]); ověřit(/.../, ["fretka", "trajekt", "ferrari"], ["ferrum", "převod A"]); ověřit(/.../, ["jak lahodné", "prostorný pokoj"], ["zničující", "vědomí"]); ověřit(/.../, ["špatná interpunkce."], ["uniknout tečku"]); ověřit(/.../, ["hottenottententen"], ["ne", "hotten totten tenten"]); ověřit(/.../, ["červený ptakopysk", "kolísající se hnízdo"], ["zemní postel", "učící se opice"]); funkce ověřit(regexp, ano, ne) ( // Ignorovat nedokončená cvičení if (regexp.source == "...") return; yes.forEach(function(s) ( if (!regexp.test(s)) console .log("Nenalezeno "" + s + """ )); no.forEach(funkce(y) ( if (regexp.test(s)) console.log("Neočekávaný výskyt "" + s + " "" ));

Citáty v textu
Řekněme, že jste napsali příběh a všude jste naznačovali dialogy jednoduché uvozovky. Nyní chcete nahradit uvozovky v dialogu dvojitými uvozovkami a ponechat jednoduché uvozovky ve zkratkách slov jako nejsou.

Vymyslete vzor, ​​který rozlišuje mezi těmito dvěma způsoby použití uvozovek, a napište volání metody nahradit, která provede nahrazení.

Zase čísla
Posloupnosti čísel lze nalézt pomocí jednoduchého regulárního výrazu /\d+/.

Napište výraz, který najde pouze zapsaná čísla JavaScript stylu. Musí podporovat možné mínus nebo plus před číslem, desetinnou čárku a vědecký zápis 5e-3 nebo 1E10 – opět s možným plusem nebo mínusem. Všimněte si také, že před nebo za tečkou nemusí být nutně čísla, ale číslo se nemůže skládat z jedné tečky. Tedy 0,5 nebo 5. – platná čísla, ale jeden bod sám o sobě není.

// Zde zadejte pravidelnou sekvenci. číslo var = /^...$/; // Testy: ["1", "-1", "+15", "1.55", ".5", "5.", "1.3e2", "1E-4", "1e+12"] .forEach(funkce(y) ( if (!číslo.test(y)) console.log("Nenalezeno "" + s + """); )); ["1a", "+-1", "1.2.3", "1+1", "1e4.5", ".5.", "1f5", "."].forEach(funkce) ( if (číslo.test(y)) console.log("Nesprávně přijato "" + s + """); ));




Horní