Sprawdzanie wyrażeń regularnych JavaScript pod kątem liczby. Przykład: usuwanie wielkich liter

Wyrażenie regularne JavaScript to typ obiektu używany do dopasowywania sekwencji znaków w łańcuchach.

Tworzenie pierwszego wyrażenia regularnego

Istnieją dwa sposoby tworzenia wyrażeń regularnych: przy użyciu literału wyrażenia regularnego lub przy użyciu konstruktora wyrażeń regularnych. Każdy z nich reprezentuje ten sam wzór: symbol „ C", śledzony przez " A" a następnie symbol " T».

// literał wyrażenia regularnego jest ujęty w ukośniki (/)
var opcja1 = /kot/;
// Konstruktor wyrażeń regularnych
var opcja2 = nowy RegExp("kot");

Ogólną zasadą jest, że jeśli wyrażenie regularne ma być stałe, co oznacza, że ​​się nie zmieni, lepiej jest użyć literału wyrażenia regularnego. Jeśli będzie się to zmieniać lub będzie zależeć od innych zmiennych, lepiej zastosować metodę z konstruktorem.

Metoda RegExp.prototype.test().

Pamiętasz, jak mówiłem, że wyrażenia regularne są obiektami? Oznacza to, że mają wiele metod. Najprostszą metodą jest JavaScript test wyrażenia regularnego która zwraca wartość logiczną:

Prawda: ciąg zawiera wzorzec wyrażenia regularnego.

Fałsz: nie znaleziono dopasowania.

console.log(/cat/.test(“kot mówi miau”));
// Prawidłowy
console.log(/cat/.test(“pies szczeka”));
// niepoprawne

Ściągawka z podstaw wyrażeń regularnych

Sekret wyrażeń regularnych polega na zapamiętywaniu typowych znaków i grup. Gorąco polecam spędzić kilka godzin na poniższym wykresie, a następnie wrócić i studiować dalej.

Symbolika

  • . – (kropka) dopasowuje dowolny pojedynczy znak z wyjątkiem łamania linii;
  • *  –  dopasowuje poprzednie wyrażenie, które jest powtarzane 0 lub więcej razy;
  • +  –  dopasowuje poprzednie wyrażenie, które powtarza się 1 lub więcej razy;
  • ? – poprzednie wyrażenie jest opcjonalne ( pasuje 0 lub 1 raz);
  • ^ – odpowiada początkowi linii;
  • $ – dopasowuje koniec linii.

Grupy postaci

  • D– dopasowuje dowolny pojedynczy znak numeryczny.
  • w– dopasowuje dowolny znak (cyfrę, literę lub znak podkreślenia).
  • [XYZ]– zestaw znaków. Dopasowuje dowolny pojedynczy znak z zestawu określonego w nawiasach. Można także określić zakresy znaków, np. .
  • [XYZ]+– dopasowuje znak ze zbioru, który powtarza się jeden lub więcej razy.
  • [^A–Z]– w zestawie znaków „^” jest używane jako znak negacji. W w tym przykładzie Wzorzec pasuje do wszystkiego, co nie jest wielką literą.

Flagi:

W wyrażeniu regularnym JavaScript dostępnych jest pięć opcjonalnych flag. Można ich używać osobno lub razem i umieszcza się je po ukośniku zamykającym. Na przykład: /[ A-Z]/g. Tutaj pokażę tylko dwie flagi.

G– wyszukiwanie globalne.

I– wyszukiwanie bez rozróżniania wielkości liter.

Dodatkowe projekty

(X)–  przechwytywanie nawiasów. To wyrażenie dopasowuje x i zapamiętuje to dopasowanie, dzięki czemu można go później użyć.

(?:X)– nawiasy nie przechwytujące. Wyrażenie dopasowuje x, ale nie pamięta dopasowania.

Dopasowuje x tylko wtedy, gdy następuje po nim y.

Przetestujmy materiał, który studiowaliśmy

Najpierw przetestujmy wszystkie powyższe. Powiedzmy, że chcemy sprawdzić ciąg znaków pod kątem dowolnych liczb. Aby to zrobić, możesz użyć konstrukcji „d”.

konsola.log(/d/.test("12-34"));
// Prawidłowy

Powyższy kod zwraca wartość true, jeśli w ciągu znaków znajduje się co najmniej jedna cyfra. Co zrobić, jeśli chcesz sprawdzić ciąg znaków pod kątem zgodności z formatem? Aby zdefiniować format, możesz użyć wielu znaków „d”:

console.log(/dd-dd/.test("12-34"));
//Prawidłowy
console.log(/dd-dd/.test("1234"));
//zło

Jeśli nie obchodzi Cię, w jaki sposób liczby pojawiają się przed i po znaku „-” w wyrażeniu regularnym JavaScript online, możesz użyć symbolu „+”, aby pokazać, że wzorzec „d” występuje jeden lub więcej razy:

console.log(/d+-d+/.test("12-34"));
// Prawidłowy
konsola.log(/d+-d+/.test("1-234"));
// Prawidłowy
konsola.log(/d+-d+/.test("-34"));
// niepoprawne

Dla uproszczenia możesz używać nawiasów do grupowania wyrażeń. Powiedzmy, że mamy miauczącego kota i chcemy sprawdzić wzór” miauczeć"(miauczeć):

console.log(/me+(ow)+w/.test("meeeeowowww"));
// Prawidłowy

Teraz rozwiążmy to.

m => dopasuj jedną literę „m”;

e + => dopasuj literę „e” jeden lub więcej razy;

(ow) + => dopasuj litery „ow” jeden lub więcej razy;

w => pasuje do litery „w”;

„m” + „eeee” + „owowow” + „w”.

Gdy operatory takie jak „+” są użyte bezpośrednio po nawiasach, wpływają one na całą zawartość nawiasów.

Operatora”? " Wskazuje, że poprzedni znak jest opcjonalny. Jak zobaczysz poniżej, oba przypadki testowe zwracają wartość true, ponieważ znaki „s” są oznaczone jako opcjonalne.

console.log(/cats? mówi?/i.test("Kot mówi miau");
//Prawidłowy
console.log(/cats? mówi?/i.test("Koty mówią miau");
//Prawidłowy

Jeśli chcesz znaleźć znak ukośnika, musisz go uciec za pomocą ukośnika odwrotnego. To samo dotyczy innych znaków o specjalnym znaczeniu, takich jak znak zapytania. Oto przykład wyrażenia regularnego JavaScript, jak ich szukać:

var slashSearch = ///;
var pytanieWyszukiwanie = /?/;

  • D jest taki sam jak: każda konstrukcja odpowiada symbolowi cyfrowemu.
  • w– to jest to samo co [ A —Za —z 0-9_]: oba wyrażenia pasują do dowolnego pojedynczego znaku alfanumerycznego lub podkreślenia.

Przykład: dodawanie spacji do linii w stylu wielbłąda

W tym przykładzie jesteśmy naprawdę zmęczeni wielbłądziem stylem pisania i potrzebujemy sposobu na dodanie spacji między słowami. Oto przykład:

usuńCc("camelCase") // => powinien zwrócić "camel Case"

Istnieje proste rozwiązanie wykorzystujące wyrażenie regularne. Najpierw musimy wszystko znaleźć wielkie litery. Można to zrobić za pomocą wyszukiwania zestawu znaków i modyfikatora globalnego.

Pasuje do znaku „C” w „camelCase”

Jak teraz dodać spację przed „C”?

Musimy używać urzekających nawiasów! Pozwalają znaleźć dopasowanie i zapamiętać je do późniejszego wykorzystania! Użyj nawiasów chwytających, aby zapamiętać wielką literę, którą znajdziesz:

Dostęp do przechwyconej wartości można uzyskać później w następujący sposób:

Powyżej używamy $1, aby uzyskać dostęp do przechwyconej wartości. Nawiasem mówiąc, gdybyśmy mieli dwa zestawy nawiasów przechwytujących, użylibyśmy 1 $ i 2 $ w odniesieniu do przechwyconych wartości i podobnie dla więcej urzekające nawiasy.

Jeśli chcesz użyć nawiasów, ale nie musisz przechwytywać tej wartości, możesz użyć nawiasów nieprzechwytujących: (?: x ). W tym przypadku znaleziono dopasowanie do x, ale nie zostało ono zapamiętane.

Wróćmy do bieżącego zadania. Jak zaimplementować przechwytywanie nawiasów? Używanie metody zastępowania wyrażeń regularnych JavaScript! Jako drugi argument przekazujemy „1$”. Ważne jest, aby używać tutaj cudzysłowów.

funkcja usuńCc(str)(
return str.replace(/()/g, "1$");
}


Spójrzmy jeszcze raz na kod. Chwytamy wielką literę, a następnie zastępujemy ją tą samą literą. Wewnątrz cudzysłowów wstaw spację, po której następuje zmienna $1 . W rezultacie po każdej dużej literze otrzymujemy spację.

funkcja usuńCc(str)(
return str.replace(/()/g, " 1 $");
}
usuńCc("camelCase") // "Camel Case"
usuńCc("helloWorldItIsMe") // "Witaj świecie, to ja"

Przykład: usuwanie wielkich liter

Teraz mamy ciąg znaków z mnóstwem niepotrzebnych wielkich liter. Czy zastanawiałeś się, jak je usunąć? Najpierw musimy zaznaczyć wszystkie wielkie litery. Następnie szukamy zestawu znaków za pomocą modyfikatora globalnego:

Ponownie użyjemy metody zamiany, ale jak tym razem zrobić małe litery?

funkcja LowerCase(str)(
return str.replace(//g, ???);
}


Wskazówka: W metodzie zamiany() możesz określić funkcję jako drugi parametr.

Użyjemy funkcji strzałkowej, aby uniknąć przechwytywania wartości znalezionego dopasowania. W przypadku użycia funkcji w metodzie zamiany wyrażenia regularnego JavaScript funkcja zostanie wywołana po znalezieniu dopasowania, a wynik funkcji zostanie użyty jako ciąg zastępczy. Co więcej, jeśli dopasowanie jest globalne i zostanie znalezionych wiele dopasowań, funkcja zostanie wywołana dla każdego znalezionego dopasowania.

funkcja LowerCase(str)(
return str.replace(//g, (u) => u.toLowerCase());
}
LowerCase("Etui na wielbłąda") // "Skrzynia na wielbłąda"
LowerCase("Witaj świecie, to ja") // "Witaj, świecie, to ja"

Przykład: zamień pierwszą literę na dużą

capitalize("przypadek wielbłąda") // => powinien zwrócić "przypadek wielbłąda"

Użyjmy ponownie funkcji w metodzie zamiany(). Tym razem jednak wystarczy wyszukać pierwszy znak w ciągu. Przypomnijmy, że używany jest do tego symbol „^”.

Zatrzymajmy się na chwilę nad symbolem „^”. Zapamiętaj przykład podany wcześniej:

console.log(/cat/.test("kot mówi miau"));
//Prawidłowy

Podczas dodawania znaku „^” funkcja nie zwraca już prawdy, ponieważ słowo „kot” nie znajduje się na początku linii.

Niektórzy ludzie w obliczu problemu myślą: „Och, użyję wyrażeń regularnych”. Teraz mają dwa problemy.
Jamie Zawinski

Yuan-Ma powiedział: „Cięcie drewna w poprzek słojów wymaga dużej siły. Programowanie całej struktury problemu wymaga dużej ilości kodu.
Mistrz Yuan-Ma, „Księga programowania”

Narzędzia i techniki programowania przetrwały i rozprzestrzeniały się w sposób chaotyczny i ewolucyjny. Czasami przetrwają nie piękni i błyskotliwi, ale po prostu ci, którzy wystarczająco dobrze sprawdzają się w swojej dziedzinie – na przykład, jeśli zostaną zintegrowani z inną, odnoszącą sukcesy technologią.

W tym rozdziale omówimy takie narzędzie - wyrażenia regularne. Jest to sposób na opisanie wzorców w danych łańcuchowych. Tworzą mały, samodzielny język, który jest zawarty w JavaScript oraz wielu innych językach i narzędziach.

Regularne harmonogramy są zarówno bardzo dziwne, jak i niezwykle przydatne. Ich składnia jest tajemnicza, a interfejs programowania JavaScript jest nieporęczny. Ale to potężne narzędzie do eksploracji i przetwarzania ciągów znaków. Kiedy je zrozumiesz, staniesz się skuteczniejszym programistą.

Tworzenie wyrażenia regularnego

Regularny – typ obiektu. Można go utworzyć wywołując konstruktor RegExp lub pisząc wymagany szablon, otoczone ukośnikami.

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

Obydwa wyrażenia regularne reprezentują ten sam wzorzec: znak „a”, po którym następuje znak „b”, po którym następuje znak „c”.

Jeśli użyjesz konstruktora RegExp, wzór zostanie zapisany jako zwykły ciąg, więc obowiązują wszystkie zasady dotyczące ukośników odwrotnych.

Drugi wpis, w którym wzór znajduje się pomiędzy ukośnikami, traktuje ukośniki odwrotne w inny sposób. Po pierwsze, ponieważ wzór kończy się ukośnikiem, musimy umieścić ukośnik odwrotny przed ukośnikiem, który chcemy uwzględnić w naszym wzorcu. Dodatkowo ukośniki odwrotne, które nie są częścią znaki specjalne typ \n zostanie zachowany (a nie ignorowany, jak w przypadku łańcuchów) i zmieni znaczenie wzorca. Niektóre znaki, takie jak znak zapytania czy plus, mają w wyrażeniach regularnych specjalne znaczenie i jeśli trzeba znaleźć taki znak, należy go również poprzedzić ukośnikiem odwrotnym.

Var osiemnaściePlus = /osiemnaście\+/;

Aby wiedzieć, które znaki muszą być poprzedzone ukośnikiem, musisz poznać listę wszystkich znaków specjalnych w wyrażeniach regularnych. Nie jest to jeszcze możliwe, dlatego w razie wątpliwości wystarczy umieścić ukośnik odwrotny przed dowolnym znakiem, który nie jest literą, cyfrą lub spacją.

Sprawdzanie dopasowań

Stali bywalcy mają kilka metod. Najprostszy to test. Jeśli przekażesz mu ciąg znaków, zwróci wartość logiczną wskazującą, czy ciąg zawiera wystąpienie danego wzorca.

Console.log(/abc/.test("abcde")); // → true console.log(/abc/.test("abxde")); // → fałsz

Zwykła sekwencja składająca się wyłącznie ze znaków innych niż specjalne jest po prostu sekwencją tych znaków. Jeśli abc znajduje się gdziekolwiek w testowanym wierszu (nie tylko na początku), test zwróci wartość true.

Szukam zestawu znaków

Możesz także sprawdzić, czy ciąg znaków zawiera abc, używając funkcji IndexOf. Regularne wzory pozwalają pójść dalej i stworzyć bardziej złożone wzory.

Powiedzmy, że musimy znaleźć dowolną liczbę. Kiedy w wyrażeniu regularnym umieścimy zbiór znaków w nawiasach kwadratowych, oznacza to, że ta część wyrażenia pasuje do dowolnego znaku w nawiasach.

Obydwa wyrażenia znajdują się w wierszach zawierających liczbę.

Console.log(//.test("w 1992")); // → true console.log(//.test("w 1992")); // → prawda

W nawiasach kwadratowych myślnik pomiędzy dwoma znakami służy do określenia zakresu znaków, których kolejność jest określona przez kodowanie Unicode. Znaki od 0 do 9 są tam po prostu w rzędzie (kody od 48 do 57), więc przechwytuje je wszystkie i dopasowuje dowolną liczbę.

Kilka grup znaków ma własne wbudowane skróty.

\d Dowolna liczba
\w Znak alfanumeryczny
\s Znak odstępu (spacja, tabulator, nowa linia itp.)
\D to nie liczba
\W nie jest znakiem alfanumerycznym
\S nie jest znakiem odstępu
. dowolny znak z wyjątkiem nowego wiersza

W ten sposób możesz ustawić format daty i godziny, np. 30.01.2003 15:20, za pomocą następującego wyrażenia:

Var dateTime = /\d\d-\d\d-\d\d\d\d \d\d:\d\d/; konsola.log(datagodzina.test("30-01-2003 15:20")); // → true console.log(dateTime.test("30-sty-2003 15:20")); // → fałsz

Wygląda okropnie, prawda? Istnieje zbyt wiele ukośników odwrotnych, co utrudnia zrozumienie wzoru. Poprawimy to nieco później.

Ukośników odwrotnych można także używać w nawiasach kwadratowych. Na przykład [\d.] oznacza dowolną liczbę lub kropkę. Zauważ, że kropka w nawiasach kwadratowych traci swoje szczególne znaczenie i staje się po prostu kropką. To samo dotyczy innych znaków specjalnych, takich jak +.

Można odwrócić zestaw znaków — to znaczy, że trzeba znaleźć dowolny znak z wyjątkiem tych, które znajdują się w zestawie — umieszczając znak ^ bezpośrednio po otwierającym nawiasie kwadratowym.

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

Powtarzające się części szablonu

Wiemy, jak znaleźć jedną liczbę. A co jeśli będziemy musieli znaleźć całą liczbę – ciąg jednej lub więcej cyfr?

Jeśli po czymś w regularnej kolejności postawisz znak +, będzie to oznaczać, że ten element można powtórzyć więcej niż raz. /\d+/ oznacza jedną lub więcej cyfr.

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

Gwiazdka * ma prawie to samo znaczenie, ale pozwala na wystąpienie wzorca zero razy. Jeśli po czymś następuje gwiazdka, to nigdy nie przeszkadza to w umieszczeniu wzorca w linii - po prostu pojawia się tam zero razy.

Znak zapytania sprawia, że ​​część wzorca jest opcjonalna, co oznacza, że ​​może wystąpić zero lub raz. W poniższym przykładzie może pojawić się znak u, ale wzór pasuje nawet wtedy, gdy tak nie jest.

Var sąsiad = /sąsiad?r/; konsola.log(sąsiad.test("sąsiad")); // → true console.log(neighbor.test("sąsiad")); // → prawda

Aby określić dokładną liczbę wystąpień wzorca, użyj aparat ortodontyczny. (4) po elemencie oznacza, że ​​musi on wystąpić 4 razy w wierszu. Można także określić przerwę: (2,4) oznacza, że ​​element musi wystąpić co najmniej 2 i nie więcej niż 4 razy.

Inna wersja formatu daty i godziny, w której dozwolone są dni, miesiące i godziny składające się z jednej lub dwóch cyfr. Jest też trochę bardziej czytelny.

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

Możesz używać spacji otwartych, pomijając jedną z liczb. (,5,) oznacza, że ​​wzór może wystąpić od zera do pięciu razy, a (5,) oznacza od pięciu lub więcej.

Grupowanie podwyrażeń

Aby użyć operatorów * lub + na wielu elementach jednocześnie, możesz użyć nawiasów. Część wyrażenia regularnego ujęta w nawiasy jest uważana za jeden element z punktu widzenia operatorów.

Var kreskówkiPłacz = /boo+(hoo+)+/i; console.log(cartoonCrying.test("Boohoooohoohooo")); // → prawda

Plusy pierwszy i drugi dotyczą tylko drugich o w boo i hoo. Trzeci + odnosi się do całej grupy (hoo+), znajdując jedną lub więcej takich sekwencji.

Litera i na końcu wyrażenia sprawia, że ​​w wyrażeniu regularnym nie jest uwzględniana wielkość liter, więc B odpowiada b.

Mecze i grupy

Metoda testowa jest najprostszą metodą sprawdzania wyrażeń regularnych. Informuje tylko, czy znaleziono dopasowanie, czy nie. Regularni mają również metodę exec, która zwróci wartość null, jeśli nic nie zostanie znalezione, lub w przeciwnym razie zwróci obiekt z informacją o dopasowaniu.

Var dopasowanie = /\d+/.exec("jeden dwa 100"); konsola.log(dopasowanie); // → ["100"] console.log(match.index); // → 8

Obiekt zwrócony przez exec posiada właściwość indeks, która zawiera numer znaku, od którego nastąpiło dopasowanie. Ogólnie rzecz biorąc, obiekt wygląda jak tablica ciągów znaków, gdzie pierwszym elementem jest ciąg znaków, który został sprawdzony pod kątem dopasowania. W naszym przykładzie będzie to ciąg liczb, którego szukaliśmy.

Ciągi mają metodę dopasowania, która działa w podobny sposób.

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

Jeśli wyrażenie regularne zawiera podwyrażenia pogrupowane w nawiasy, tekst pasujący do tych grup również pojawi się w tablicy. Pierwszy element jest zawsze pełnym dopasowaniem. Druga to część pasująca do pierwszej grupy (ta, której nawiasy wystąpiły jako pierwsze), następnie druga grupa i tak dalej.

Var quotedText = /"([^"]*)"/; console.log(quotedText.exec("powiedziała "cześć"")); // → [""cześć"", "cześć"]

Jeśli grupa w ogóle nie zostanie znaleziona (na przykład, jeśli następuje po niej znak zapytania), jej pozycja w tablicy jest niezdefiniowana. Jeśli grupa pasuje kilka razy, w tablicy znajdzie się tylko ostatnie dopasowanie.

Console.log(/bad(ly)?/.exec("zły")); // → ["zły", niezdefiniowany] console.log(/(\d)+/.exec("123")); // → ["123", "3"]

Grupy są przydatne do pobierania części ciągów. Jeśli nie chcemy po prostu sprawdzić, czy ciąg znaków ma datę, ale wyodrębnić ją i utworzyć obiekt reprezentujący datę, możemy ująć ciągi liczb w nawiasy i wybrać datę z wyniku exec.

Ale najpierw mała dygresja, w której poznamy preferowany sposób przechowywania daty i czasu w JavaScript.

Typ daty

JavaScript ma standardowy typ obiekt dla dat - a raczej chwil w czasie. Nazywa się Data. Jeśli po prostu utworzysz obiekt daty za pomocą nowego, otrzymasz bieżąca data i czas.

Console.log(nowa data()); // → niedziela 09 listopada 2014 00:07:57 GMT+0300 (CET)

Można także utworzyć obiekt zawierający zadany czas

Console.log(nowa data(2015, 9, 21)); // → środa 21 października 2015 00:00:00 GMT+0300 (CET) console.log(new Date(2009, 11, 9, 12, 59, 59, 999)); // → środa 09 grudnia 2009 12:59:59 GMT+0300 (CET)

JavaScript wykorzystuje konwencję, w której numery miesięcy zaczynają się od zera, a numery dni zaczynają się od jedynki. To jest głupie i śmieszne. Bądź ostrożny.

Ostatnie cztery argumenty (godziny, minuty, sekundy i milisekundy) są opcjonalne i w przypadku ich braku są ustawiane na zero.

Znaczniki czasu są przechowywane jako liczba milisekund, które upłynęły od początku 1970 r. Dla czasów sprzed 1970 r. użyj liczby ujemne(wynika to z konwencji czasowej Uniksa, która powstała mniej więcej w tym czasie). Metoda getTime obiektu date zwraca tę liczbę. Jest naturalnie duży.
konsola.log(nowa data(2013, 11, 19).getTime()); // → 1387407600000 console.log(new Date(1387407600000)); // → czw. 19 grudnia 2013 r. 00:00:00 GMT+0100 (CET)

Jeśli konstruktorowi Date podasz jeden argument, będzie on traktowany jako liczba milisekund. Bieżącą wartość milisekund można uzyskać tworząc obiekt Date i wywołując metodę getTime lub wywołując funkcję Date.now.

Obiekt Date ma metody getFullYear, getMonth, getDate, getHours, getMinutes i getSeconds w celu pobrania jego składników. Istnieje również metoda getYear, która zwraca raczej bezużyteczny dwucyfrowy kod, taki jak 93 lub 14.

Ujmując odpowiednie części szablonu w nawiasy, możemy bezpośrednio z ciągu znaków utworzyć obiekt daty.

Funkcja findDate(string) ( var dateTime = /(\d(1,2))-(\d(1,2))-(\d(4))/; var match = dateTime.exec(string); return new Date(Number(dopasowanie), Liczba(dopasowanie) - 1, Liczba(dopasowanie)); ) console.log(findDate("30-1-2003")); // → czw. 30 stycznia 2003 00:00:00 GMT+0100 (CET)

Granice słów i linii

Niestety, findDate równie szczęśliwie wyodrębni bezsensowną datę 00-1-3000 z ciągu „100-1-30000”. Dopasowanie może nastąpić w dowolnym miejscu ciągu, tzw w tym przypadku zacznie się po prostu od drugiego znaku i zakończy na przedostatnim.

Jeśli chcemy wymusić dopasowanie całego ciągu, używamy znaczników ^ i $. ^ dopasowuje początek linii, a $ dopasowuje koniec. Dlatego /^\d+$/ dopasowuje ciąg zawierający tylko jedną lub więcej cyfr, /^!/ dopasowuje ciąg zaczynający się od wykrzyknika, a /x^/ nie pasuje do żadnego ciągu (nie może być x).

Jeśli natomiast chcemy mieć pewność, że data zaczyna się i kończy na granicy słowa, używamy znaku \b. Granicą słowa może być początek lub koniec wiersza albo dowolne miejsce w wierszu, w którym po jednej stronie znajduje się znak alfanumeryczny \w, a po drugiej znak niealfanumeryczny.

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

Należy pamiętać, że etykieta granicy nie jest symbolem. Jest to po prostu ograniczenie, co oznacza, że ​​dopasowanie następuje tylko wtedy, gdy spełniony jest określony warunek.

Szablony z możliwością wyboru

Załóżmy, że chcesz sprawdzić, czy tekst zawiera nie tylko liczbę, ale także liczbę, po której następuje świnia, krowa lub kurczak w liczbie pojedynczej lub mnogiej.

Można by napisać trzy wyrażenia regularne i sprawdzić je jedno po drugim, ale jest lepszy sposób. Symbol | oznacza wybór pomiędzy wzorami po lewej i prawej stronie. I możemy powiedzieć co następuje:

Var AnimalCount = /\b\d+ (świnia|krowa|kurczak)s?\b/; console.log(animalCount.test("15 świń")); // → true console.log(animalCount.test("15 świń")); // → fałsz

Nawiasy wyznaczają część wzorca, do której zastosowano |, a wiele takich operatorów można umieścić jeden po drugim, aby wskazać wybór spośród więcej niż dwóch opcji.

Wyszukiwarka

Wyrażenia regularne można traktować jako schematy blokowe. Poniższy diagram opisuje najnowszy przykład hodowli zwierząt gospodarskich.

Wyrażenie dopasowuje ciąg znaków, jeśli możliwe jest znalezienie ścieżki od lewej strony diagramu do prawej. Zapamiętujemy aktualną pozycję w linii i za każdym razem, gdy przechodzimy przez prostokąt, sprawdzamy, czy część linii bezpośrednio po naszej pozycji w niej odpowiada zawartości prostokąta.

Oznacza to, że sprawdzanie dopasowania naszego zwykłego znaku w ciągu „the 3 pigs” podczas przeglądania schematu blokowego wygląda następująco:

Na pozycji 4 znajduje się granica słowa i mijamy pierwszy prostokąt
- zaczynając od 4. pozycji znajdujemy liczbę i przechodzimy przez drugi prostokąt
- na pozycji 5 jedna ścieżka zamyka się z powrotem przed drugim prostokątem, a druga biegnie dalej do prostokąta ze spacją. Mamy spację, a nie liczbę i wybieramy drugą ścieżkę.
- teraz jesteśmy na pozycji 6, na początku „świń” i na potrójnym rozgałęzieniu ścieżek. W kolejce nie ma „krowy” ani „kurczaka”, jest natomiast „świnia”, więc wybieramy tę ścieżkę.
- na pozycji 9 za potrójnym rozwidleniem jedna ścieżka omija „s” i przechodzi do prostokąta granicznego ostatniego słowa, a druga przechodzi przez „s”. Mamy „s”, więc idziemy tam.
- na pozycji 10 jesteśmy na końcu linii i pasuje tylko granica słowa. Koniec linii jest uważany za granicę i przechodzimy przez ostatni prostokąt. A teraz pomyślnie znaleźliśmy nasz szablon.

Zasadniczo sposób działania wyrażeń regularnych polega na tym, że algorytm zaczyna się od początku ciągu i próbuje tam znaleźć dopasowanie. W naszym przypadku jest granica słowa, więc przechodzi przez pierwszy prostokąt - ale nie ma tam liczby, więc natrafia na drugi prostokąt. Następnie przechodzi do drugiego znaku w ciągu i próbuje tam znaleźć dopasowanie... I tak dalej, aż znajdzie dopasowanie lub dotrze do końca ciągu, w którym to przypadku nie zostanie znalezione dopasowanie.

Odrzuty

Wyrażenie regularne /\b(+b|\d+|[\da-f]h)\b/ dopasowuje liczbę binarną, po której następuje litera b, liczbę dziesiętną bez przyrostka lub liczbę szesnastkową (cyfry od 0 do 9 lub symbole od a do h), po których następuje h. Odpowiedni schemat:

Podczas wyszukiwania dopasowania może się zdarzyć, że algorytm wybierze górną ścieżkę (liczbę binarną), nawet jeśli w ciągu znaków nie ma takiej liczby. Jeśli na przykład jest linia „103”, jasne jest, że dopiero po osiągnięciu cyfry 3 algorytm zrozumie, że jest na złej ścieżce. Ogólnie rzecz biorąc, linia odpowiada regularnej sekwencji, ale nie w tym wątku.

Następnie algorytm się cofa. Na rozwidleniu zapamiętuje aktualną pozycję (w naszym przypadku jest to początek linii, tuż za granicą słowa), dzięki czemu możesz wrócić i spróbować inną ścieżką, jeśli wybrana nie działa. Dla ciągu „103” po napotkaniu trójki powróci i spróbuje przejść ścieżką dziesiętną. To zadziała, więc dopasowanie zostanie znalezione.

Algorytm zatrzymuje się, gdy tylko znajdzie pełne dopasowanie. Oznacza to, że nawet jeśli kilka opcji może być odpowiednich, używana jest tylko jedna z nich (w kolejności, w jakiej występują w regularnej kolejności).

Wycofywanie ma miejsce podczas używania operatorów powtórzeń, takich jak + i *. Jeśli szukasz /^.*x/ w ciągu "abcxe", część regularna.* spróbuje wykorzystać cały ciąg. Algorytm zorientuje się wtedy, że potrzebuje także „x”. Ponieważ na końcu łańcucha nie ma znaku „x”, algorytm będzie próbował znaleźć dopasowanie, cofając się o jeden znak. Po abcx również nie ma x, po czym następuje powrót, tym razem do podłańcucha abc. Po linii znajduje x i zgłasza pomyślne dopasowanie na pozycjach od 0 do 4.

Możesz napisać regularną procedurę, która będzie prowadzić do wielokrotnych wycofywania zmian. Ten problem występuje, gdy wzorzec może wielokrotnie dopasowywać dane wejściowe. różne sposoby. Na przykład, jeśli popełnimy błąd podczas zapisywania wyrażenia regularnego dla liczby binarne, możemy przypadkowo napisać coś takiego jak /(+)+b/.

Jeśli algorytm miałby szukać takiego wzorca w długim ciągu zer i jedynek, który nie ma litery „b” na końcu, najpierw przechodziłby przez wewnętrzną pętlę, aż skończyłyby mu się cyfry. Wtedy zauważy, że na końcu nie ma „b”, cofnie się o jedną pozycję, przejdzie przez zewnętrzną pętlę, ponownie się podda, spróbuj przetoczyć się do innej pozycji wzdłuż wewnętrznej pętli… I będzie kontynuował wyszukiwać w ten sposób, używając obu pętli. Oznacza to, że ilość pracy z każdym znakiem linii podwoi się. Nawet dla kilkudziesięciu postaci znalezienie dopasowania zajmie bardzo dużo czasu.

metoda zastępcza

Ciągi mają metodę zamiany, która może zastąpić część ciągu innym ciągiem.

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

Pierwszym argumentem może być także wyrażenie regularne. W takim przypadku zastępowane jest pierwsze wystąpienie wyrażenia regularnego w wierszu. Po dodaniu opcji „g” (globalnej) do wyrażenia regularnego zastępowane są wszystkie wystąpienia, a nie tylko pierwsze

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

Sensowne byłoby przekazanie opcji „zamień wszystko” poprzez osobny argument lub osobną metodę, np. zamień wszystko. Ale niestety opcja jest przesyłana przez sam zwykły system.

Pełna moc wyrażeń regularnych ujawnia się, gdy użyjemy linków do grup znajdujących się w ciągu znaków, określonych w wyrażeniu regularnym. Na przykład mamy wiersz zawierający imiona i nazwiska osób, po jednym imieniu w wierszu, w formacie „Nazwisko, imię”. Jeśli musimy je zamienić i usunąć przecinek, aby otrzymać „Imię Nazwisko”, piszemy, co następuje:

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

$1 i $2 w linii zastępczej odnoszą się do grup znaków ujętych w nawiasy. 1 $ jest zastępowany tekstem pasującym do pierwszej grupy, 2 $ do drugiej grupy i tak dalej, aż do 9 $. Całe dopasowanie jest zawarte w zmiennej $&.

Możesz także przekazać funkcję jako drugi argument. Dla każdej zamiany zostanie wywołana funkcja, której argumentami będą znalezione grupy (i cała pasująca część linii), a jej wynik zostanie wstawiony do nowej linii.

Prosty przykład:

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

Oto ciekawszy:

Var stock = „1 cytryna, 2 kapusty i 101 jaj”; funkcja minusOne(dopasowanie, ilość, jednostka) ( ilość = Liczba(liczba) - 1; if (kwota == 1) // pozostała tylko jedna, usuń „s” na końcu unit = unit.slice(0, unit. długość - 1); else if (kwota == 0) ilość = "nie"; zwrócona kwota + " " + jednostka; ) console.log(stock.replace(/(\d+) (\w+)/g, minusOne) ); // → bez cytryny, 1 kapusta i 100 jajek

Kod pobiera ciąg znaków, znajduje wszystkie wystąpienia liczb, po których następuje słowo, i zwraca ciąg znaków, w którym każda liczba jest zmniejszona o jeden.

Grupa (\d+) przechodzi do argumentu kwoty, a (\w+) do argumentu jednostki. Funkcja konwertuje kwotę na liczbę - i to zawsze działa, ponieważ naszym wzorcem jest \d+. A następnie wprowadza zmiany w słowie, na wypadek, gdyby pozostał tylko 1 element.

Chciwość

Łatwo jest użyć zamiany do napisania funkcji, która usuwa wszystkie komentarze z kodu JavaScript. Oto pierwsza próba:

Funkcja stripComments(kod) ( return code.replace(/\/\/.*|\/\*[^]*\*\//g, ""); ) console.log(stripComments("1 + /* 2*/3")); // → 1 + 3 console.log(stripComments("x = 10;// dziesięć!")); // → x = 10; console.log(stripComments("1 /* a */+/* b */ 1")); // → 1 1

Część przed operatorem „lub” odpowiada dwóm ukośnikom, po których następuje dowolna liczba znaków z wyjątkiem znaków nowej linii. Część usuwająca komentarze wielowierszowe jest bardziej złożona. Używamy [^], tj. dowolny znak, który nie jest pusty, aby znaleźć dowolny znak. Nie możemy użyć kropki, ponieważ komentarze blokowe są kontynuowane Nowa linia, a znak nowej linii nie odpowiada kropce.

Ale wynik poprzedniego przykładu jest nieprawidłowy. Dlaczego?

Część [^]* najpierw spróbuje przechwycić jak najwięcej znaków. Jeśli z tego powodu następna część zwykłej sekwencji nie znajdzie dopasowania, cofnie się o jeden znak i spróbuje ponownie. W przykładzie algorytm próbuje przechwycić całą linię, a następnie wycofuje się. Po cofnięciu 4 znaków znajdzie w wierszu */ - a nie o to nam chodziło. Chcieliśmy pobrać tylko jeden komentarz, a nie przechodzić na koniec wiersza i znajdować ostatni komentarz.

Z tego powodu mówimy, że operatory powtórzeń (+, *, ? i ()) są zachłanne, co oznacza, że ​​najpierw chwytają tyle, ile mogą, a potem wracają. Jeśli umieścisz pytanie po takim operatorze (+?, *?, ??, ()?), zamienią się one w nie zachłanne i zaczną znajdować najmniejsze możliwe wystąpienia.

I tego właśnie potrzebujemy. Zmuszając gwiazdkę do znalezienia dopasowań w minimalnej możliwej liczbie znaków w wierszu, zużywamy tylko jeden blok komentarzy i nic więcej.

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

Wiele błędów występuje podczas używania operatorów zachłannych zamiast operatorów nie zachłannych. Używając operatora powtarzania, zawsze najpierw rozważ operator, który nie jest zachłanny.

Dynamiczne tworzenie obiektów RegExp

W niektórych przypadkach dokładny wzór nie jest znany w momencie pisania kodu. Na przykład będziesz musiał poszukać nazwy użytkownika w tekście i ująć ją w podkreślenia. Ponieważ nazwę poznasz dopiero po uruchomieniu programu, nie możesz używać notacji z ukośnikiem.

Można jednak skonstruować ciąg znaków i użyć konstruktora RegExp. Oto przykład:

Nazwa zmiennej = „harry”; var tekst = "A Harry ma bliznę na czole."; var regexp = new RegExp("\\b(" + nazwa + ")\\b", "gi"); console.log(text.replace(regexp, "_$1_")); // → I _Harry_ ma bliznę na czole.

Tworząc granice słów, musimy używać podwójnych ukośników, ponieważ piszemy je w normalnej linii, a nie w regularnej kolejności z ukośnikami. Drugi argument RegExp zawiera opcje wyrażeń regularnych - w naszym przypadku „gi”, tj. globalne i nie uwzględnia wielkości liter.

Ale co, jeśli nazwa brzmi „dea+hlrd” (jeśli nasz użytkownik jest kulhatzkerem)? W efekcie otrzymamy nic nieznaczące wyrażenie regularne, które nie znajdzie dopasowań w ciągu znaków.

Możemy dodać ukośniki odwrotne przed dowolnym znakiem, którego nie lubimy. Nie możemy dodać ukośników odwrotnych przed literami, ponieważ \b lub \n są znakami specjalnymi. Ale możesz bez problemu dodać ukośniki przed znakami niealfanumerycznymi.

Nazwa zmiennej = "dea+hlrd"; var tekst = "Ten dea+hlrd denerwuje wszystkich."; var escaped = nazwa.replace(/[^\w\s]/g, "\\$&"); var regexp = new RegExp("\\b(" + ucieczka + ")\\b", "gi"); console.log(text.replace(regexp, "_$1_")); // → To _dea+hlrd_ zirytowało wszystkich.

metoda wyszukiwania

Metody IndexOf nie można używać z wyrażeniami regularnymi. Istnieje jednak metoda wyszukiwania, która oczekuje tylko wyrażenia regularnego. Podobnie jak IndexOf, zwraca indeks pierwszego wystąpienia lub -1, jeśli żadne nie występuje.

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

Niestety, nie ma sposobu, aby powiedzieć metodzie, aby szukała dopasowania rozpoczynającego się od określonego przesunięcia (jak można to zrobić za pomocą indeksu). To byłoby pomocne.

właściwość lastIndex

Metoda exec również nie działa wygodnym sposobem rozpocznij wyszukiwanie od podanej pozycji w ciągu. Ale daje to niewygodny sposób.

Obiekt regex ma właściwości. Jednym z nich jest source, które zawiera ciąg znaków. Kolejnym jest lastIndex, który pod pewnymi warunkami kontroluje, gdzie rozpocznie się kolejne wyszukiwanie wystąpień.

Warunki te obejmują obecność opcji globalnej g oraz konieczność wyszukiwania przy użyciu metody exec. Bardziej rozsądnym rozwiązaniem byłoby po prostu zezwolenie na przekazanie dodatkowego argumentu do exec, ale rozsądek nie jest podstawową cechą interfejsu wyrażenia regularnego JavaScript.

Wzór Var = /y/g; wzór.lastIndex = 3; var dopasowanie = wzór.exec("xyzzy"); konsola.log(match.index); // → 4 console.log(pattern.lastIndex); // → 5

Jeśli wyszukiwanie zakończyło się pomyślnie, wywołanie exec aktualizuje właściwość lastIndex, aby wskazywała pozycję po znalezionym wystąpieniu. Jeżeli nie powiodło się, lastIndex jest ustawiany na zero - podobnie jak lastIndex nowo utworzonego obiektu.

W przypadku używania globalnej zmiennej regularnej i wielu wywołań exec te automatyczne aktualizacje lastIndex mogą powodować problemy. Twój zwykły serwer może rozpocząć wyszukiwanie od pozycji pozostawionej po poprzednim połączeniu.

Var cyfra = /\d/g; console.log(digit.exec("oto: 1")); // → ["1"] console.log(digit.exec("i teraz: 1")); // → zero

Innym interesującym efektem opcji g jest to, że zmienia sposób działania metody dopasowania. Wywołany z tą opcją, zamiast zwracać tablicę podobną do wyniku exec, znajduje wszystkie wystąpienia wzorca w ciągu i zwraca tablicę znalezionych podciągów.

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

Uważaj więc na globalne zmienne regularne. Przypadki, w których są potrzebne - zastąp wywołania lub miejsca, w których specjalnie używasz lastIndex - to prawdopodobnie wszystkie przypadki, w których należy ich użyć.

Cykle występowania

Typowym zadaniem jest iteracja przez wszystkie wystąpienia wzorca w ciągu znaków, aby uzyskać dostęp do obiektu dopasowania w treści pętli za pomocą lastIndex i exec.

Var input = "Linia zawierająca 3 liczby... 42 i 88."; liczba zmiennych = /\b(\d+)\b/g; var dopasowanie; while (match = liczba.exec(input)) console.log("Znalezione ", dopasowanie, " na ", dopasowanie.index); // → Znaleziono 3 na 14 // Znaleziono 42 na 33 // Znaleziono 88 na 40

Wykorzystuje fakt, że wartością przypisania jest wartość przypisana. Używanie match = re.exec(input) jako warunku w pętla while, przeszukujemy na początku każdej iteracji, przechowujemy wynik w zmiennej i kończymy pętlę, gdy zostaną znalezione wszystkie dopasowania.

Parsowanie plików INI

Na zakończenie rozdziału przyjrzyjmy się problemowi związanemu z używaniem wyrażeń regularnych. Wyobraźmy sobie, że piszemy program, który zbiera informacje o naszych wrogach za pośrednictwem Internetu. tryb automatyczny. (Nie będziemy pisać całego programu, tylko część, która odczytuje plik ustawień. Przepraszamy.) Plik wygląda następująco:

Searchengine=http://www.google.com/search?q=$1 złośliwość=9.7 ; przed komentarzami umieszcza się średnik; każda sekcja odnosi się do innego wroga, pełne imię i nazwisko=Larry Doe typ=witryna byka w przedszkolu=http://www.geocities.com/CapeCanaveral/11451 pełna nazwa=Gargamel typ=wyjście złego czarodzieja=/home/marijn/enemies/gargamel

Dokładny format pliku (który jest dość powszechnie używany i zwykle nazywany jest INI) jest następujący:

Puste linie i linie rozpoczynające się od średnika są ignorowane
- linie ujęte w nawiasy kwadratowe rozpoczynają nową sekcję
- linie zawierające identyfikator alfanumeryczny, po którym następuje = dodaj ustawienie w tej sekcji

Cała reszta to nieprawidłowe dane.

Naszym zadaniem jest przekształcenie takiego ciągu znaków w tablicę obiektów, każdy z właściwością name i tablicą ustawień. Dla każdej sekcji potrzebny jest jeden obiekt i jeszcze jeden dla ustawienia ogólne u góry pliku.

Ponieważ plik musi być analizowany wiersz po wierszu, dobrze jest zacząć od podzielenia pliku na wiersze. Aby to zrobić, w rozdziale 6 użyliśmy string.split("\n"). Niektóre systemy operacyjne używają nie jednego znaku \n do podziału wiersza, ale dwa - \r\n. Ponieważ metoda split przyjmuje jako argument wyrażenia regularne, możemy dzielić linie za pomocą wyrażenia /\r?\n/, dopuszczając zarówno pojedyncze \n, jak i \r\n pomiędzy wierszami.

Funkcja parseINI(string) ( // Zacznijmy od obiektu zawierającego ustawienia najwyższego poziomu var currentSection = (nazwa: null, pola: ); var kategorie = ; string.split(/\r?\n/).forEach(funkcja (linia ) ( var dopasowanie; if (/^\s*(;.*)?$/.test(line)) ( return; ) else if (match = line.match(/^\[(.*)\ ]$ /)) ( currentSection = (nazwa: dopasowanie, pola: ); kategorie.push(bieżąca sekcja); ) else if (match = line.match(/^(\w+)=(.*)$/)) ( currentSection.fields.push((nazwa: dopasowanie, wartość: dopasowanie)); ) else ( wyrzuć nowy błąd("Wiersz "" + wiersz + "" zawiera nieprawidłowe dane."); ) )); zwróć kategorie; )

Kod przechodzi przez wszystkie linie, aktualizując bieżący obiekt sekcji „bieżąca sekcja”. Najpierw sprawdza, czy linię można zignorować za pomocą wyrażenia regularnego /^\s*(;.*)?$/. Czy możesz sobie wyobrazić, jak to działa? Część w nawiasach pasuje do komentarzy, prawda? sprawia, że ​​zwykły znak będzie pasował także do linii składających się wyłącznie ze spacji.

Jeśli linia nie jest komentarzem, kod sprawdza, czy rozpoczyna nową sekcję. Jeśli tak, tworzy nowy obiekt dla bieżącej sekcji, do którego dodawane są kolejne ustawienia.

Ostatnią znaczącą możliwością jest to, że ciąg znaków jest normalnym ustawieniem i w takim przypadku jest dodawany do bieżącego obiektu.

Jeśli żadna z opcji nie zadziała, funkcja zgłosi błąd.

Zwróć uwagę, że częste użycie ^ i $ gwarantuje, że wyrażenie dopasuje cały ciąg, a nie tylko jego część. Jeśli ich nie użyjesz, kod na ogół będzie działał, ale czasami będzie generował dziwne wyniki, a błąd będzie trudny do wyśledzenia.

Konstrukcja if (match = string.match(...)) jest podobna do sztuczki polegającej na użyciu przypisania jako warunku w pętli while. Często nie wiesz, że wywołanie dopasowania zakończy się sukcesem, więc dostęp do obiektu wynikowego możesz uzyskać tylko w bloku if, który go sprawdza. Aby nie przerwać pięknego łańcucha kontroli if, wynik wyszukiwania przypisujemy do zmiennej i natychmiast używamy tego przypisania jako kontroli.

Symbole międzynarodowe

Ze względu na początkowo prostą implementację języka, a następnie utrwalenie takiej implementacji „w granicie”, wyrażenia regularne JavaScript są głupie ze znakami, których nie ma w języku angielskim. Na przykład znak „litery” z punktu widzenia wyrażeń regularnych JavaScript może być jedną z 26 liter alfabetu angielskiego i z jakiegoś powodu także znakiem podkreślenia. Litery takie jak é lub β, które są wyraźnie literami, nie pasują do \w (i będą pasować do \W, które nie jest literą).

Dziwnym zbiegiem okoliczności historycznie \s (spacja) dopasowuje wszystkie znaki uważane za białe znaki w Unicode, w tym takie jak spacja nierozrywająca lub mongolski separator samogłosek.

Niektóre implementacje wyrażeń regularnych w innych językach mają specjalną składnię do wyszukiwania specjalnych kategorii znaków Unicode, takich jak „wszystkie wielkie litery”, „wszystkie znaki interpunkcyjne” lub „znaki sterujące”. W planach jest dodanie takich kategorii do JavaScriptu, jednak prawdopodobnie nie zostaną one wdrożone w najbliższym czasie.

Konkluzja

Regularne to obiekty reprezentujące wzorce wyszukiwania w ciągach znaków. Używają własnej składni, aby wyrazić te wzorce.

/abc/ Sekwencja znaków
// Dowolny znak z listy
/[^abc]/ Dowolny znak z wyjątkiem znaków z listy
// Dowolny znak z interwału
/x+/ Jedno lub więcej wystąpień wzorca x
/x+?/ Jedno lub więcej wystąpień, bez zachłanności
/x*/ Zero lub więcej wystąpień
/x?/ Zero lub jedno wystąpienie
/x(2,4)/ Od dwóch do czterech wystąpień
/(abc)/ Grupa
/a|b|c/ Dowolny z kilku wzorców
/\d/ Dowolna liczba
/\w/ Dowolny znak alfanumeryczny („litera”)
/\s/ Dowolny biały znak
/./ Dowolny znak z wyjątkiem znaków nowej linii
/\b/ Granica słowa
/^/ Początek linii
/$/ Koniec linii

Wyrażenie regularne ma metodę testową sprawdzającą, czy wzorzec znajduje się w ciągu znaków. Istnieje metoda exec, która zwraca tablicę zawierającą wszystkie znalezione grupy. Tablica posiada właściwość indeks, która zawiera numer znaku, od którego nastąpiło dopasowanie.

Ciągi mają metodę dopasowania dopasowującą wzorce oraz metodę wyszukiwania, która zwraca tylko pozycję początkową wystąpienia. Metoda zamiany może zastąpić wystąpienia wzorca innym ciągiem znaków. Dodatkowo możesz przekazać funkcję do zamiany, która zbuduje linię zastępczą na podstawie szablonu i znalezionych grup.

Zwykłe znaki mają ustawienia zapisywane po ukośniku zamykającym. Opcja i sprawia, że ​​w wyrażeniu regularnym nie jest uwzględniana wielkość liter, a opcja g sprawia, że ​​jest ono globalne, co między innymi powoduje, że metoda zamiany zastępuje wszystkie znalezione wystąpienia, a nie tylko pierwsze.

Konstruktor RegExp może służyć do tworzenia wyrażeń regularnych z ciągów znaków.

Automaty to ostry instrument z niewygodnym uchwytem. Znacznie upraszczają niektóre zadania i mogą stać się niewykonalne przy rozwiązywaniu innych, złożonych problemów. Częścią nauki używania wyrażeń regularnych jest umiejętność oparcia się pokusie wypchania ich zadaniem, do którego nie są przeznaczone.

Ćwiczenia

Nieuchronnie podczas rozwiązywania problemów napotkasz niezrozumiałe przypadki i czasami możesz wpaść w rozpacz, gdy zobaczysz nieprzewidywalne zachowanie niektórych wyrażeń regularnych. Czasami pomocne jest zbadanie zachowania zwykłego silnika za pośrednictwem usługi online, takiej jak debuggex.com, gdzie można zobaczyć jego wizualizację i porównać z pożądanym efektem.
Zwykły golf
„Golf” w kodzie to gra, w której trzeba wyrazić danego programu minimalna liczba znaków. Zwykły golf to praktyczne ćwiczenie polegające na pisaniu możliwie najmniejszych regularnych graczy w celu znalezienia danego wzorca i tylko tyle.

Dla każdej z podlinii napisz wyrażenie regularne, aby sprawdzić ich położenie w linii. Zwykły silnik powinien znaleźć tylko te określone podciągi. Nie martw się o granice słów, chyba że zostało to wyraźnie zaznaczone. Jeśli masz działający, regularny wzór, spróbuj go zmniejszyć.

Samochód i kot
- pop i prop
- fretka, prom i ferrari
- Dowolne słowo kończące się na ious
- Spacja, po której następuje kropka, przecinek, dwukropek lub średnik.
- Słowo dłuższe niż sześć liter
- Słowo bez liter e

// Wprowadź swoje wyrażenia regularne zweryfikować(/.../, ["mój samochód", "złe koty"], ["kamper", "sztuka wysoka"]); zweryfikować(/.../, ["popkultura", "szalone rekwizyty"], ["plop"]); zweryfikować(/.../, ["fretka", "prom", "ferrari"], ["ferrum", "przelew A"]); zweryfikować(/.../, ["jak pysznie", "przestronny pokój"], ["rujnujący", "świadomość"]); zweryfikować(/.../, ["zła interpunkcja."], ["uciec przed kropką"]); zweryfikować(/.../, ["hottenottententen"], ["nie", "hotten totten tenten"]); zweryfikować(/.../, ["czerwony dziobak", "chwiejące się gniazdo"], ["ziemne łóżko", "ucząca się małpa"]); funkcja zweryfikować(regexp, tak, nie) ( // Ignoruj ​​niedokończone ćwiczenia if (regexp.source == "...") return; tak.forEach(funkcja(y) ( if (!regexp.test(s)) konsola .log("Nie znaleziono "" + s + """); )); no.forEach(funkcje ( if (regexp.test(s)) console.log("Nieoczekiwane wystąpienie "" + s + " ""); )); )

Cytaty w tekście
Załóżmy, że napisałeś opowiadanie i użyłeś pojedynczych cudzysłowów, aby wskazać dialog. Teraz chcesz zastąpić cudzysłowy dialogowe podwójnymi cudzysłowami i pozostawić pojedyncze cudzysłowy w skrótach dla słów takich jak are not.

Stwórz wzorzec rozróżniający te dwa zastosowania cudzysłowów i napisz wywołanie metody zamiany, która dokonuje zamiany.

Znowu liczby
Ciągi liczb można znaleźć za pomocą prostego wyrażenia regularnego /\d+/.

Napisz wyrażenie, które znajdzie tylko liczby zapisane w stylu JavaScript. Powinien zawierać możliwy minus lub plus przed liczbą, przecinek dziesiętny i notację naukową 5e-3 lub 1E10 - ponownie z możliwy plus lub minus. Należy również pamiętać, że przed lub po kropce niekoniecznie muszą znajdować się liczby, ale liczba nie może składać się z pojedynczej kropki. Oznacza to, że 0,5 lub 5 są prawidłowymi liczbami, ale jedna kropka sama w sobie nie.

// Wpisz tutaj regularną sekwencję. liczba zmiennych = /^...$/; // Testy: ["1", "-1", "+15", "1,55", ".5", "5.", "1.3e2", "1E-4", "1e+12"] .forEach(funkcje) ( if (!number.test(s)) console.log("Nie znaleziono "" + s + """); )); ["1a", "+-1", "1.2.3", "1+1", "1e4.5", ".5.", "1f5", "."].forEach(funkcje) ( if (number.test(s)) console.log("Niepoprawnie zaakceptowane "" + s + """); ));

Regex i wyrażenia regularne są onieśmielające dla początkujących, ale niezbędne dla każdego programisty. Przyjrzyjmy się wyrażeniom regularnym na 5 prostych przykładach z JavaScriptem.

Jeśli masz problem i chcesz go rozwiązać za pomocą wyrażeń regularnych, masz teraz dwa problemy. Jest takie powiedzenie. Wyrażenia regularne występujące w kodzie czasami powodują strach i nienawiść u osób, które ich nie znają.

Ale tak naprawdę każde wyrażenie regularne jest po prostu wyrażeniem szablonowym, które może rozwiązać problem całej funkcji w jednym wierszu. Aby jednak zbudować wyrażenie regularne, należy wziąć pod uwagę zestaw rygorystycznych zasad, w których początkujący może się pogubić i popełnić błędy.

Pasujące znaki

Najbardziej podstawowe wyrażenia regularne to te, które dopasowują pojedyncze znaki. Oto ich zasady:

1. Kropka (.) odpowiada dowolnemu znakowi. Jeśli chcesz wyszukać konkretny punkt, musisz go opuścić, używając znaku „\” (\.).

2. Znak zapytania (?) oznacza, że ​​poprzedni znak jest opcjonalny. Aby wyszukać sam znak zapytania w ciągu, należy go również poprzedzić znakiem „\” (\?).

var tekst = "Lorem ipsum dolor sit amet, consectetur adipiscing elit lest. Donec convallis dignissim ligula, et rutrum est elat vistibulum eu."; // Wystarczą zarówno „elit”, jak i „elat”. Kropka oznacza, że ​​wystarczy dowolny symbol. var regex = /el.t/g; konsola.log(tekst.match(regex)); // „est” i „lest” będą działać równie dobrze. Znak zapytania sprawia, że ​​„l” jest opcjonalne. var regex2 = /l?est/g; konsola.log(tekst.match(regex2));

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

// Wystarczą zarówno „elit”, jak i „elat”. Kropka oznacza, że ​​wystarczy dowolny symbol.

var regex = /el.t/g ;

konsola. log(tekst. dopasowanie(regex));

// „est” i „lest” będą działać równie dobrze. Znak zapytania sprawia, że ​​„l” jest opcjonalne.

var regex2 = /l?est/g;

konsola. log(tekst. dopasowanie(regex2));

Dopasuj wiele znaków

Zestaw to jeden lub więcej znaków ujętych w nawiasy, na przykład . To wyrażenie będzie szukać tylko tego zestawu znaków w ciągu — w tym przykładzie tylko a, b lub c. Wręcz przeciwnie, możesz wyszukiwać wystąpienia dowolnych symboli, z wyjątkiem użycia symbolu „^”. [^abc] dopasuje dowolny znak inny niż a, b lub c. Można także określić zakres znaków lub cyfr, na przykład .

Istnieją wbudowane zestawy znaków, które ułatwiają pisanie wyrażeń regularnych. Nazywa się je skrótami lub skrótami. Zamiast tego możesz na przykład napisać \D. Istnieją skróty dla innych znaków (w tym cyfr i znaków podkreślenia) - \w i \W, a także spacji - \s i \S.

// Tylko „kot” i „może” będą działać, a nie „samochód”. var tekst = "samochód dla kota"; konsola.log(tekst.match(/ca/g)); // Wszystko przejdzie oprócz cat i can (jest symbol ^) console.log(text.match(/ca[^tn]/g)); // Inny przykład, w którym przekazywane będą tylko liczby. text = "Poproszę 8 filiżanek kawy."; console.log("Ile filiżanek: " + tekst.match(//g)); // Łatwiejszy sposób za pomocą skrótu \d console.log("Ile filiżanek: " + tekst.match(/\d/g)); // Przekazuje wszystko oprócz liczb console.log(text.match(/\D/g));

// Tylko „kot” i „może” będą działać, a nie „samochód”.

var tekst = "samochód dla kota";

konsola. log(tekst. dopasowanie(/ca/g));

// Przekazuje wszystko z wyjątkiem cat i can (jest tam symbol ^)

konsola. log (tekst . dopasowanie (/ca[^tn]/g ) ) ;

// Kolejny przykład, w którym przekazywane będą tylko liczby

tekst = „Poproszę 8 filiżanek kawy”.;

konsola. log("Ile filiżanek: " + tekst. dopasowanie (//g ) );

// Łatwiejszy sposób za pomocą skrótu \d

konsola. log("Ile filiżanek: " + tekst. dopasowanie (/\d/g ) ) ;

// Wszystko przeminie oprócz liczb

konsola. log(tekst. dopasowanie(/\D/g));

Pasujące słowa

W większości przypadków należy wyszukiwać całe słowa, a nie pojedyncze znaki. Odbywa się to za pomocą modyfikatorów (+) i (-), które powtarzają znak lub zestaw znaków.

Dodanie (X) określa dokładną liczbę powtórzeń, (x, y) – zakres (x i y to liczby).

Dodatkowo istnieje specjalny wzór \b, który dopasowuje granice na końcach słów.

var text = "Witajcie ludzie z 1974 roku. Pochodzę z przyszłości. W 2014 roku będziemy mieć broń laserową, latające deski i zamieszkamy na Księżycu!"; // Znajdzie lata. \d+ dopasuje jeden lub więcej znaków var yearRegex = /\d+/g; console.log("Lata: ", tekst.match(rokRegex)); // Znajduje wszystkie zdania. Nasze zdania zaczynają się wielką literą i kończą kropką lub wykrzyknikiem. var zdanieRegex = /.+?(\.|!)/g; console.log("Zdania: ", tekst.match(zdanieRegex)); // Znajduje wszystkie słowa zaczynające się na „h”. Odpowiednie są dla nas zarówno wielkie, jak i małe litery, dlatego używamy modyfikatora i // \b, aby zdefiniować granicę słowa. var hWords = /\bh\w+/ig; console.log("Słowa H: ", tekst.match(hWords)); // Znajduje wszystkie słowa o długości od 4 do 6 znaków var findWords = /\b\w(4,6)\b/g; console.log("Słowa od 4 do 6 znaków: ", text.match(findWords)); // Znajdź słowa dłuższe niż 5 znaków console.log("Słowa 5 znaków lub dłuższe: ", text.match(/\b\w(5,)\b/g)); // Znajduje słowa o długości dokładnie 6 znaków console.log("Słowa o długości dokładnie 6 znaków: ", text.match(/\b\w(6)\b/g));

var tekst = „Witajcie, ludzie z 1974 roku. Pochodzę z przyszłości. W 2014 roku będziemy mieć broń laserową, latające deski i zamieszkamy na Księżycu!”;

// Znajdzie lata. \d+ dopasowuje jeden lub więcej znaków

var rokRegex = /\d+/g ;

konsola. log("Lata: ", tekst. dopasowanie (rokRegex));

// Znajduje wszystkie zdania. Nasze zdania zaczynają się wielką literą i kończą kropką lub wykrzyknikiem.

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

konsola. log("Zdania: ", tekst. dopasowanie(zdanieRegex));

// Znajduje wszystkie słowa zaczynające się na „h”. Odpowiednie są dla nas zarówno wielkie, jak i małe litery, dlatego używamy modyfikatora i

// \b, aby określić granice słów.

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

konsola. log("Słowa H: ", tekst. dopasowanie (hWords));

// Znajduje wszystkie słowa o długości od 4 do 6 znaków

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

konsola. dziennik( „Słowa od 4 do 6 znaków: „, tekst. dopasowanie(znajdźSłowa));

// Znajdź słowa dłuższe niż 5 znaków

konsola. log("Słowa 5 znaków lub dłuższe: ", tekst. dopasowanie (/\b\w(5,)\b/g ) );

// Znajdź słowa o długości dokładnie 6 znaków

konsola. dziennik( „Słowa o długości dokładnie 6 znaków:”, tekst. dopasowanie (/\b\w(6)\b/g ) ) ;

Walidacja całego ciągu

W JavaScript takich wyrażeń można używać do sprawdzania poprawności danych wejściowych użytkownika z pól tekstowych. Aby sprawdzić poprawność ciągów znaków, stosuje się regularne wyrażenie regularne powiązane z początkiem i końcem fragmentu tekstu, używając w tym celu wyrażeń ^ (początek linii) i $ (koniec linii). Symbole te zapewniają, że zapisany wzór będzie obejmował całą długość tekstu, a nie tylko jego część.

Dodatkowo w tym przypadku używamy metody test() obiektu regex, która podczas sprawdzania, czy wyrażenie regularne pasuje do ciągu zwraca wartość true lub false.

// Mamy tablicę ciągów, znajdźmylinks..com/", "123461", "https://site/?s=google", "http://nieprawidłowy adres 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);

// Mamy tablicę ciągów znaków, znajdźmy linki.

ciągi znaków = [

„https://strona/” ,

„to nie jest adres URL”,

„https://google.com/” ,

"123461" ,

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

„http://nieprawidłowy adres URL”,

„abc http://nieprawidłowy.url/”

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

zmienne adresy URL = ;

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

if (regex. test (stringi [ i ] ) ) (

adresy URL. push(stringi[i]);

konsola. log("Prawidłowe adresy URL: ", adresy URL);

Wyszukaj i zamień

Inny wspólne zadanie, co ułatwia użycie wyrażeń regularnych, polega na wyszukiwaniu i zastępowaniu tekstu.

Wyrażenia regularne

Wyrażenie regularne jest obiektem opisującym wzorzec znaków. Klasa RegExp w języku JavaScript reprezentuje wyrażenia regularne, a obiekty klas String i RegExp definiują metody korzystające z wyrażeń regularnych do wykonywania operacji dopasowywania wzorców oraz wyszukiwania i zastępowania tekstu. Gramatyka wyrażeń regularnych w JavaScript zawiera dość kompletny podzbiór składni wyrażeń regularnych używanej w Perlu 5, więc jeśli masz doświadczenie z językiem Perl, możesz z łatwością opisywać wzorce w programach JavaScript.

Funkcje wyrażeń regularnych Perla, które nie są obsługiwane w ECMAScript, obejmują flagi s (tryb jednowierszowy) i x (składnia rozszerzona); sekwencje ucieczki \a, \e, \l, \u, \L, \U, \E, \Q, \A, \Z, \z i \G oraz inne rozszerzone konstrukcje zaczynające się od (?.

Definiowanie wyrażeń regularnych

W Regularny JavaScript wyrażenia są reprezentowane przez obiekty RegExp. Obiekty RegExp można tworzyć za pomocą konstruktora RegExp(), ale częściej tworzy się je przy użyciu specjalnej składni dosłownej. Podobnie jak literały łańcuchowe są określane jako znaki ujęte w cudzysłów, tak literały wyrażeń regularnych są określane jako znaki ujęte w parę ukośników (/). Zatem Twój kod JavaScript może zawierać takie linie:

Wzór Var = /s$/;

Ta linia tworzy nowy obiekt RegExp i przypisuje go do zmiennej wzorca. Ten obiekt RegExp szuka ciągów kończących się na „s”. To samo wyrażenie regularne można zdefiniować za pomocą konstruktora RegExp():

Wzór Var = nowy RegExp("s$");

Specyfikacja wzorca wyrażenia regularnego składa się z sekwencji znaków. Większość znaków, w tym wszystkie alfanumeryczne, dosłownie opisuje znaki, które muszą być obecne. Oznacza to, że wyrażenie regularne /java/ pasuje do wszystkich linii zawierających podciąg „java”.

Inne znaki w wyrażeniach regularnych nie są przeznaczone do wyszukiwania ich dokładnych odpowiedników, lecz mają specjalne znaczenie. Na przykład wyrażenie regularne /s$/ zawiera dwa znaki. Pierwszy znak s oznacza wyszukiwanie znaku dosłownego. Po drugie, $ jest specjalnym metaznakiem oznaczającym koniec linii. Zatem to wyrażenie regularne dopasowuje dowolny ciąg znaków kończący się znakiem s.

W poniższych sekcjach opisano różne znaki i metaznaki używane w wyrażeniach regularnych w JavaScript.

Dosłowne znaki

Jak wspomniano wcześniej, wszystkie znaki alfabetu i cyfry w wyrażeniach regularnych pasują do siebie. Składnia wyrażeń regularnych w JavaScript umożliwia także określenie pewnych znaków niealfabetycznych przy użyciu sekwencji ucieczki rozpoczynających się od znaku ukośnika odwrotnego (\). Na przykład sekwencja \n odpowiada znakowi nowej linii. Symbole te są wymienione w poniższej tabeli:

Niektóre znaki interpunkcyjne mają specjalne znaczenie w wyrażeniach regularnych:

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

Znaczenie tych symboli wyjaśniono w poniższych sekcjach. Niektóre z nich mają specjalne znaczenie tylko w określonych kontekstach wyrażeń regularnych, podczas gdy w innych kontekstach są interpretowane dosłownie. Jednak ogólnie rzecz biorąc, aby dosłownie uwzględnić którykolwiek z tych znaków w wyrażeniu regularnym, należy go poprzedzić znakiem ukośnika odwrotnego. Inne znaki, takie jak cudzysłowy i @, nie mają specjalnego znaczenia i po prostu dopasowują się do siebie w wyrażeniach regularnych.

Jeśli nie pamiętasz dokładnie, które znaki powinny być poprzedzone \, możesz bezpiecznie umieścić ukośnik odwrotny przed dowolnym znakiem. Należy jednak pamiętać, że wiele liter i cyfr staje się specjalne znaczenie, więc litery i cyfry, których szukasz, nie powinny być poprzedzone znakiem \. Aby uwzględnić sam znak ukośnika odwrotnego w wyrażeniu regularnym, należy oczywiście poprzedzić go innym znakiem ukośnika odwrotnego. Na przykład poniższe wyrażenie regularne dopasowuje dowolny ciąg znaków zawierający ukośnik odwrotny: /\\/.

Klasy postaci

Poszczególne znaki literału można łączyć w klasy znaków, umieszczając je w nawiasach kwadratowych. Klasa znaku odpowiada dowolnemu znakowi zawartemu w tej klasie. Dlatego wyrażenie regularne // dopasowuje jeden ze znaków a, b lub c.

Klasy znaków ujemnych można również zdefiniować tak, aby pasowały do ​​dowolnego znaku z wyjątkiem tych określonych w nawiasach. Klasa znaku negacji jest określona przez znak ^ jako pierwszy znak po lewym nawiasie. Wyrażenie regularne /[^abc]/ dopasowuje dowolny znak inny niż a, b lub c. W klasach znaków zakres znaków można określić za pomocą łącznika. Wszystkie małe litery łacińskie można znaleźć za pomocą wyrażenia //, a dowolną literę lub cyfrę z zestawu znaków łacińskich można znaleźć za pomocą wyrażenia //.

Niektóre klasy znaków są szczególnie powszechne, dlatego składnia wyrażeń regularnych w JavaScript zawiera znaki specjalne i sekwencje specjalne, które je reprezentują. Zatem \s dopasowuje spację, tabulator i dowolne białe znaki Unicode, a \S dopasowuje dowolne białe znaki inne niż Unicode.

Poniższa tabela zawiera listę tych znaków specjalnych i składnię klas znaków. (Należy pamiętać, że niektóre sekwencje specjalne klas znaków pasują tylko do znaków ASCII i nie są rozszerzone do pracy ze znakami Unicode. Możesz jawnie zdefiniować własne klasy znaków Unicode, na przykład /[\u0400-\u04FF]/ dopasowuje dowolny znak cyrylicy .)

Klasy znaków wyrażeń regularnych JavaScript
Symbol Korespondencja
[...] Dowolny ze znaków pokazanych w nawiasach
[^...] Dowolny ze znaków niewymienionych w nawiasach
. Dowolny znak inny niż znak nowej linii lub inny ogranicznik linii Unicode
\w Dowolny znak tekstowy ASCII. Równowartość
\W Dowolny znak, który nie jest znakiem tekstowym ASCII. Odpowiednik [^a-zA-Z0-9_]
\S Dowolny biały znak z zestawu Unicode
\S Dowolny znak inny niż biały znak z zestawu Unicode. Należy pamiętać, że znaki \w i \S to nie to samo
\D Dowolne liczby ASCII. Równowartość
\D Dowolny znak inny niż cyfry ASCII. Odpowiednik [^0-9]
[\B] Dosłowny znak Backspace

Należy pamiętać, że sekwencje specjalne znaków klasowych można ująć w nawiasy kwadratowe. \s pasuje do dowolnego znaku odstępu, a \d pasuje do dowolnej cyfry, stąd /[\s\d]/ pasuje do dowolnego znaku lub cyfry spacji.

Powtórzenie

Znając dotychczas zdobytą wiedzę o składni wyrażeń regularnych, liczbę dwucyfrową możemy opisać jako /\d\d/ lub liczbę czterocyfrową jako /\d\d\d\d/, ale nie możemy np. , opisz liczbę składającą się z dowolnej liczby cyfr lub ciągu trzech liter, po których następuje opcjonalna cyfra. Te bardziej złożone wzorce wykorzystują składnię wyrażeń regularnych, która określa, ile razy dany element wyrażenia regularnego może zostać powtórzony.

Powtarzające się symbole zawsze odpowiadają wzorowi, do którego są zastosowane. Niektóre rodzaje powtórzeń są używane dość często i dostępne są specjalne symbole wskazujące te przypadki. Na przykład + dopasowuje jedno lub więcej wystąpień poprzedniego wzorca. Poniższa tabela zawiera podsumowanie składni powtórzeń:

Poniższe wiersze pokazują kilka przykładów:

Wzór Var = /\d(2,4)/; // Dopasowuje liczbę zawierającą wzór od dwóch do czterech cyfr = /\w(3)\d?/; // Dopasuj dokładnie trzy znaki wyrazu i jeden opcjonalny wzór cyfr = /\s+java\s+/; // Dopasowuje słowo „java” z jedną lub większą liczbą spacji // przed i po nim wzór = /[^(]*/; // Dopasowuje zero lub więcej znaków innych niż nawias otwierający

Zachowaj ostrożność podczas używania znaków powtórzenia * i ?. Mogą pasować do braku określonego przed nimi wzorca, a co za tym idzie, do braku znaków. Na przykład wyrażenie regularne /a*/ dopasowuje ciąg „bbbb”, ponieważ nie zawiera znaku a.

Podane w tabeli znaki powtórzeń reprezentują maksymalną możliwą liczbę powtórzeń, która pozwoli na dopasowanie kolejnych części wyrażenia regularnego. Mówimy, że jest to zachłanne powtarzanie. Możliwe jest również wdrożenie powtórzeń wykonywanych w sposób niezachłanny. Wystarczy wskazać po symbolu (lub symbolach) powtórzenie znak zapytania: ??, +?, *? lub nawet (1,5)?.

Na przykład wyrażenie regularne /a+/ dopasowuje jedno lub więcej wystąpień litery a. Zastosowany do ciągu „aaa” pasuje do wszystkich trzech liter. Z drugiej strony wyrażenie /a+?/ dopasowuje jedno lub więcej wystąpień litery a i wybiera najmniejszą możliwą liczbę liczba znaków. Zastosowany do tego samego ciągu, ten wzór pasuje tylko do pierwszej litery a.

„Bezchciwe” powtarzanie nie zawsze daje oczekiwany rezultat. Rozważmy wzór /a+b/, który dopasowuje jedno lub więcej znaków a, po których następuje litera b. Po zastosowaniu do ciągu „aaab” odpowiada całemu ciągowi.

Sprawdźmy teraz „niechciwą” wersję /a+?b/. Można by pomyśleć, że pasowałoby to do b poprzedzonego tylko jednym a. Jeśli zastosuje się je do tego samego ciągu, oczekuje się, że „aaab” będzie pasować do pojedynczego znaku a i ostatni znak B. Jednak ten wzorzec faktycznie pasuje do całego ciągu, podobnie jak wersja zachłanna. Faktem jest, że wyszukiwanie wzorców wyrażeń regularnych odbywa się poprzez znalezienie pierwszej pozycji w ciągu, od której możliwe staje się dopasowanie. Ponieważ dopasowanie jest możliwe począwszy od pierwszego znaku ciągu, krótsze dopasowania rozpoczynające się od kolejnych znaków nie są nawet brane pod uwagę.

Alternatywy, grupowanie i linki

Gramatyka wyrażeń regularnych zawiera znaki specjalne służące do definiowania alternatyw, grupowania podwyrażeń i odniesień do poprzednich podwyrażeń. Symbol rury | służy do oddzielania alternatyw. Na przykład /ab|cd|ef/ dopasowuje albo ciąg „ab”, albo ciąg „cd”, albo ciąg „ef”, a wzorzec /\d(3)|(4)/ dopasowuje albo trzy cyfry lub cztery małe litery.

Należy pamiętać, że alternatywy są przetwarzane od lewej do prawej, aż do znalezienia dopasowania. Jeśli zostanie znalezione dopasowanie z lewą alternatywą, prawa zostanie zignorowana, nawet jeśli uda się osiągnąć „lepsze” dopasowanie. Dlatego też, gdy wzorzec /a|ab/ zostanie zastosowany do ciągu „ab”, dopasuje on tylko pierwszy znak.

Nawiasy mają wiele znaczeń w wyrażeniach regularnych. Jednym z nich jest grupowanie poszczególnych elementów w jedno podwyrażenie, tak aby elementy w przypadku użycia znaków specjalnych |, *, +, ? a inne są traktowane jako jedna całość. Na przykład wzorzec /java(script)?/ dopasowuje słowo „java”, po którym następuje opcjonalne słowo „script”, a /(ab|cd)+|ef)/ dopasowuje albo ciąg „ef”, albo jeden lub więcej powtórzenia jedynki ze ciągów „ab” lub „cd”.

Innym zastosowaniem nawiasów w wyrażeniach regularnych jest definiowanie wzorców podrzędnych we wzorcu. Gdy w ciągu docelowym zostanie znalezione dopasowanie wyrażenia regularnego, można wyodrębnić część ciągu docelowego, która pasuje do dowolnego określonego wzorca podrzędnego ujętego w nawiasy.

Załóżmy, że chcesz znaleźć jedną lub więcej małych liter, po których następuje jedna lub więcej cyfr. Aby to zrobić, możesz użyć szablonu /+\d+/. Ale załóżmy również, że chcemy tylko liczby na końcu każdego dopasowania. Jeśli umieścimy tę część wzorca w nawiasach (/+(\d+)/), możemy wyodrębnić liczby ze wszystkich znalezionych dopasowań. Jak to się stanie, zostanie opisane poniżej.

Pokrewnym zastosowaniem podwyrażeń w nawiasach jest odwoływanie się do podwyrażeń z poprzedniej części tego samego wyrażenia regularnego. Osiąga się to poprzez podanie jednej lub większej liczby cyfr po znaku \. Liczby odnoszą się do pozycji podwyrażenia w nawiasach w wyrażeniu regularnym. Na przykład \1 odnosi się do pierwszego podwyrażenia, a \3 odnosi się do trzeciego. Należy pamiętać, że podwyrażenia mogą być zagnieżdżane w sobie, dlatego podczas liczenia używana jest pozycja lewego nawiasu. Na przykład w poniższym wyrażeniu regularnym odwołanie do zagnieżdżonego podwyrażenia (kryptu) będzie wyglądać jak \2:

/(ava(cript)?)\sis\s(zabawa\w*)/

Odwołanie do poprzedniego podwyrażenia nie wskazuje na wzorzec tego podwyrażenia, ale na znaleziony tekst pasujący do tego wzorca. Dlatego referencje można wykorzystać do nałożenia ograniczenia, które wybiera części ciągu zawierające dokładnie te same znaki. Na przykład poniższe wyrażenie regularne dopasowuje zero lub więcej znaków w pojedynczym lub podwójnym cudzysłowie. Nie wymaga jednak, aby cudzysłów otwierający i zamykający były ze sobą zgodne (to znaczy, aby oba cudzysłowy były pojedyncze lub podwójne):

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

Możemy wymagać dopasowania cudzysłowów, używając takiego odniesienia:

Tutaj \1 pasuje do pierwszego podwyrażenia. W tym przykładzie łącze narzuca ograniczenie, które wymaga, aby cudzysłów zamykający odpowiadał cudzysłowowi otwierającemu. To wyrażenie regularne nie pozwala na umieszczanie pojedynczych cudzysłowów w podwójnych cudzysłowach i odwrotnie.

Możliwe jest także grupowanie elementów w wyrażeniu regularnym bez tworzenia numerowanych odniesień do tych elementów. Zamiast po prostu grupować elementy pomiędzy ( i ), rozpocznij grupę od symboli (?: i zakończ ją symbolem). Rozważmy na przykład następujący wzór:

/(ava(?:cript)?)\sis\s(zabawa\w*)/

Tutaj podwyrażenie (?:cript) jest potrzebne tylko do grupowania, aby znak powtórzenia ? mógł zostać zastosowany do grupy. Te zmodyfikowane nawiasy nie tworzą łącza, więc w tym wyrażeniu regularnym \2 odnosi się do tekstu pasującego do wzorca (zabawa\w*).

W poniższej tabeli wymieniono operatory zaznaczania, grupowania i odwołań w wyrażeniach regularnych:

Symbole wyrażeń regularnych służące do wybierania alternatyw, grupowania i Linki JavaScript
Symbol Oznaczający
| Alternatywny. Dopasowuje podwyrażenie po lewej stronie lub podwyrażenie po prawej stronie.
(...) Grupowanie. Grupuje elementy w jedną jednostkę, której można używać ze znakami *, +, ?, | i tak dalej. Zapamiętuje również znaki pasujące do tej grupy do wykorzystania w kolejnych odniesieniach.
(?:...) Tylko grupowanie. Grupuje elementy w jedną całość, ale nie zapamiętuje znaków odpowiadających tej grupie.
\numer Dopasowuje te same znaki, które zostały znalezione podczas dopasowywania numeru grupy. Grupy są podwyrażeniami umieszczonymi w (prawdopodobnie zagnieżdżonych) nawiasach. Numery grup są przypisywane poprzez liczenie lewych nawiasów od lewej do prawej. Grupy utworzone za pomocą symboli (?:) nie są numerowane.

Określanie pozycji dopasowania

Jak opisano wcześniej, wiele elementów wyrażenia regularnego pasuje do pojedynczego znaku w ciągu znaków. Na przykład \s dopasowuje pojedynczy znak odstępu. Inne elementy wyrażeń regularnych dopasowują pozycje między znakami, a nie same znaki. Na przykład \b dopasowuje granicę słowa — granicę między \w (znakiem tekstowym ASCII) a \W (znakiem nietekstowym) lub granicą między znakiem tekstowym ASCII a początkiem lub końcem wiersza.

Elementy takie jak \b nie określają żadnych znaków, które muszą znajdować się w dopasowanym ciągu, ale określają prawidłowe pozycje do dopasowania. Elementy te są czasami nazywane elementami zakotwiczenia wyrażeń regularnych, ponieważ zakotwiczają wzorzec w określonej pozycji w ciągu. Najczęściej używanymi elementami kotwiczącymi są ^ i $, które łączą wzorce odpowiednio z początkiem i końcem linii.

Na przykład słowo „JavaScript” w osobnej linii można znaleźć za pomocą wyrażenia regularnego /^JavaScript$/. Znaleźć osobne słowo„Java” (zamiast przedrostka, jak w słowie „JavaScript”), możesz spróbować użyć wzorca /\sJava\s/, który wymaga spacji przed i po słowie.

Ale takie rozwiązanie rodzi dwa problemy. Po pierwsze, znajdzie słowo „Java” tylko wtedy, gdy jest otoczone spacjami po obu stronach i nie będzie w stanie znaleźć go na początku ani na końcu linii. Po drugie, jeśli ten wzorzec będzie zgodny, zwrócony przez niego ciąg znaków będzie zawierał spacje początkowe i końcowe, a nie jest to dokładnie to, czego chcemy. Zamiast więc używać wzorca pasującego do białych znaków \s, użyjemy wzorca (lub kotwicy) pasującego do granic wyrazów \b. Wynikiem będzie następujące wyrażenie: /\bJava\b/.

Element kotwicy \B dopasowuje pozycję, która nie jest granicą słowa. Oznacza to, że wzorzec /\Bcript/ będzie pasował do słów „JavaScript” i „postscript”, a nie do słów „script” lub „Scripting”.

Dowolne wyrażenia regularne mogą również służyć jako warunki zakotwiczenia. Jeśli umieścisz wyrażenie pomiędzy znakami (?= i), stanie się ono testem dopasowania do przodu względem kolejnych znaków, wymagającym, aby te znaki pasowały do ​​określonego wzorca, ale nie były uwzględnione w ciągu dopasowania.

Na przykład, aby dopasować nazwę popularnego języka programowania, po której następuje dwukropek, można użyć wyrażenia /ava(cript)?(?=\:)/. Ten wzorzec pasuje do słowa „JavaScript” w ciągu „JavaScript: The Definitive Guide”, ale nie będzie pasował do słowa „Java” w ciągu „Java w pigułce”, ponieważ nie następuje po nim dwukropek.

Jeśli wpiszesz warunek (?!), będzie to negatywne sprawdzenie kolejnych znaków, wymagające, aby kolejne znaki nie pasowały do ​​określonego wzorca.Na przykład wzorzec /Java(?!Script)(\w* )/ dopasowuje podciąg „Java”, po którym następuje wielka litera i dowolna liczba tekstowe znaki ASCII pod warunkiem, że po podciągu „Java” nie następuje podciąg „Skrypt”. Będzie pasować do ciągu „JavaBeans”, ale nie do ciągu „Javanese”, i będzie pasować do ciągu „JavaScrip”, ale nie będzie pasować do ciągów „JavaScript” i „JavaScripter”.

Poniższa tabela zawiera listę znaków zakotwiczenia wyrażeń regularnych:

Znaki zakotwiczenia wyrażeń regularnych
Symbol Oznaczający
^ Dopasowuje początek wyrażenia łańcuchowego lub początek linii w wyszukiwaniu wielowierszowym.
$ Dopasowuje koniec wyrażenia łańcuchowego lub koniec linii w wyszukiwaniu wielowierszowym.
\B Dopasowuje granicę słowa, tj. dopasowuje pozycję pomiędzy znakiem \w a znakiem \W lub pomiędzy znakiem \w a początkiem lub końcem linii. (Zauważ jednak, że [\b] dopasowuje znak backspace.)
\B Dopasowuje pozycję, która nie jest granicą słowa.
(?=p) Pozytywna kontrola wyprzedzająca dla kolejnych znaków. Wymaga kolejnych znaków pasujących do wzorca p, ale nie uwzględnia tych znaków w dopasowanym ciągu.
(?!P) Ujemna kontrola w przód dla kolejnych znaków. Wymaga, aby następujące znaki nie pasowały do ​​wzorca p.

Flagi

I jeszcze jeden, ostatni element gramatyki wyrażeń regularnych. Flagi wyrażeń regularnych określają reguły dopasowywania wzorców wysokiego poziomu. W przeciwieństwie do reszty gramatyki wyrażeń regularnych, flagi są podawane nie pomiędzy znakami ukośnika, ale po drugim. JavaScript obsługuje trzy flagi.

Flaga I określa, że ​​w przypadku dopasowywania wzorców wielkość liter nie powinna być uwzględniana, oraz flaga g- aby wyszukiwanie miało charakter globalny, tj. muszą zostać znalezione wszystkie dopasowania w ciągu. Flaga m przeprowadza wyszukiwanie wzorców w trybie wieloliniowym. Jeśli szukane wyrażenie tekstowe zawiera znaki nowej linii, to w tym trybie znaki zakotwiczenia ^ i $ oprócz dopasowania początku i końca całego wyrażenia łańcuchowego dopasowują także początek i koniec każdego Ciąg tekstowy. Na przykład wzorzec /java$/im pasuje zarówno do „java”, jak i „Java\nis fun”.

Flagi te można łączyć w dowolną kombinację. Na przykład, aby wyszukać pierwsze wystąpienie słowa „java” (lub „Java”, „JAVA” itp.) bez uwzględniania wielkości liter, można użyć wyrażenia regularnego niewrażliwego na wielkość liter /\bjava\b/ I. Aby znaleźć wszystkie wystąpienia tego słowa w ciągu znaków, możesz dodać flagę g: /\bjava\b/gi.

Metody klasy String służące do wyszukiwania według wzorca

Do tego momentu omówiliśmy gramatykę tworzonych przez nas wyrażeń regularnych, ale nie sprawdziliśmy, w jaki sposób można ich faktycznie używać w skryptach JavaScript. W tej części omówimy metody Obiekt ciągowy, w którym wyrażenia regularne służą do dopasowywania wzorców i wyszukiwania ze zamianą. Następnie będziemy kontynuować naszą rozmowę na temat dopasowywania wzorców za pomocą wyrażeń regularnych, przyglądając się obiektowi RegExp oraz jego metodom i właściwościom.

Strings obsługuje cztery metody korzystające z wyrażeń regularnych. Najprostszą z nich jest metoda szukaj(). Przyjmuje wyrażenie regularne jako argument i zwraca pozycję pierwszego znaku dopasowanego podciągu lub -1, jeśli nie znaleziono dopasowania. Na przykład następujące wywołanie zwróci 4:

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

Jeśli argument metody search() nie jest wyrażeniem regularnym, jest najpierw konwertowany poprzez przekazanie go do konstruktora RegExp. Metoda search() nie obsługuje wyszukiwania globalnego i ignoruje flagę g w swoim argumencie.

metoda zastępować() wykonuje operację wyszukiwania i zamiany. Jako pierwszy argument przyjmuje wyrażenie regularne, a jako drugi ciąg zastępczy. Metoda przeszukuje linię, w której jest wywoływana, pod kątem dopasowania do określonego wzorca.

Jeśli wyrażenie regularne zawiera flagę g, metoda zamiany() zastępuje wszystkie znalezione dopasowania ciągiem zastępczym. W przeciwnym razie zastępuje tylko pierwsze znalezione dopasowanie. Jeśli pierwszym argumentem metody zamiany() jest ciąg znaków, a nie wyrażenie regularne, metoda przeprowadza dosłowne wyszukiwanie ciągu, zamiast konwertować go na wyrażenie regularne przy użyciu konstruktora RegExp() tak, jak robi to metoda search().

Jako przykład możemy użyć metody zamiany(), aby zachować spójną wielkość słowa „JavaScript” w całym wierszu tekstu:

// Niezależnie od wielkości znaków zastępujemy je słowem w wymaganym przypadku var wynik = "javascript".replace(/JavaScript/ig, "JavaScript");

Metoda zamiany() ma większe możliwości, niż sugerowałby ten przykład. Przypomnę, że podwyrażenia w nawiasach w wyrażeniu regularnym są numerowane od lewej do prawej i że wyrażenie regularne zapamiętuje tekst odpowiadający każdemu z podwyrażeń. Jeśli ciąg zastępczy zawiera znak $, po którym następuje liczba, metoda zamiany() zastępuje te dwa znaki tekstem pasującym do określonego podwyrażenia. Jest to bardzo przydatna funkcja. Możemy go użyć na przykład do zastąpienia cudzysłowów prostych w ciągu znaków cudzysłowami typograficznymi, które są symulowane za pomocą znaków ASCII:

// Cytat to cytat, po którym następuje dowolna liczba znaków // innych niż cudzysłowy (które pamiętamy), po których następuje kolejny cudzysłów // var quote = /"([^"]*)"/g; // Zamień proste cudzysłowy z typograficznymi i pozostaw „$1” bez zmian // treść cytatu przechowywana w 1 $ var tekst = „„JavaScript” jest interpretowanym językiem programowania.”; var wynik = tekst.replace(quote, „”$1”” ) ; // „JavaScript” jest interpretowanym językiem programowania.

Należy zauważyć, że drugim argumentem funkcji zamiany() może być funkcja, która dynamicznie oblicza ciąg zastępczy.

metoda mecz() jest najbardziej ogólną metodą klasy String, która korzysta z wyrażeń regularnych. Przyjmuje wyrażenie regularne jako jedyny argument (lub konwertuje swój argument na wyrażenie regularne, przekazując je do konstruktora RegExp()) i zwraca tablicę zawierającą wyniki wyszukiwania. Jeśli w wyrażeniu regularnym ustawiono flagę g, metoda zwraca tablicę wszystkich dopasowań występujących w ciągu. Na przykład:

// zwróci ["1", "2", "3"] var wynik = "1 plus 2 równa się 3".match(/\d+/g);

Jeśli wyrażenie regularne nie zawiera flagi g, metoda match() nie przeprowadza wyszukiwania globalnego; szuka tylko pierwszego dopasowania. Jednak metoda match() zwraca tablicę nawet wtedy, gdy metoda nie przeprowadza wyszukiwania globalnego. W tym przypadku pierwszym elementem tablicy jest znaleziony podciąg, a wszystkie pozostałe elementy są podwyrażeniami wyrażenia regularnego. Dlatego też, jeśli funkcja match() zwróci tablicę arr, wówczas arr będzie zawierać cały znaleziony ciąg znaków, arr podciąg odpowiadający pierwszemu podwyrażeniu itd. Porównując metodę zamień(), możemy powiedzieć, że zawartość $n jest wprowadzana do arr[n].

Przyjrzyj się na przykład poniższemu kodowi, który analizuje adres URL:

Var url = /(\w+):\/\/([\w.]+)\/(\S*)/; var tekst = "Odwiedź naszą stronę internetową http://www..php"; var wynik = tekst.match(url); if (result != null) ( var fullurl = wynik; // Zawiera „http://www..php” var protokół = wynik; // Zawiera „http” var host = wynik; // Zawiera „www..php” ")

Należy zauważyć, że w przypadku wyrażenia regularnego, które nie ma ustawionej flagi wyszukiwania globalnego g, metoda match() zwraca tę samą wartość, co metoda exec() wyrażenia regularnego: zwrócona tablica ma właściwości indeksowe i wejściowe, jak opisano w dyskusji na temat exec() poniżej.

Ostatnią z metod obiektu String korzystającą z wyrażeń regularnych jest podział(). Ta metoda dzieli ciąg, w którym jest wywoływana, na tablicę podciągów, używając argumentu jako ogranicznika. Na przykład:

"123 456 789".split(","); // Zwróć ["123", "456", "789"]

Metoda split() może również przyjmować jako argument wyrażenie regularne. Dzięki temu metoda jest skuteczniejsza. Na przykład możesz określić ogranicznik, który pozwala na dowolną liczbę białych znaków po obu stronach:

"1, 2, 3 , 4 , 5".split(/\s*,\s*/); // Zwróć ["1", "2", "3", "4", "5"]

Obiekt RegExp

Jak wspomniano, wyrażenia regularne są reprezentowane jako obiekty RegExp. Oprócz konstruktora RegExp() obiekty RegExp obsługują trzy metody i kilka właściwości.

Konstruktor RegExp() pobiera jeden lub dwa argumenty w postaci ciągu znaków i tworzy nowy obiekt RegExp. Pierwszym argumentem konstruktora jest ciąg znaków zawierający treść wyrażenia regularnego, tj. tekst, który musi pojawić się pomiędzy znakami ukośnika w literale wyrażenia regularnego. Należy zauważyć, że literały łańcuchowe i wyrażenia regularne używają znaku \ do reprezentowania sekwencji ucieczki, zatem przekazując wyrażenie regularne jako literał łańcuchowy do konstruktora RegExp() należy zastąpić każdy znak \ parą znaków \\.

Może brakować drugiego argumentu RegExp(). Jeśli jest określony, definiuje flagi wyrażeń regularnych. Musi to być jeden ze znaków g, i, m lub kombinacja tych znaków. Na przykład:

// Znajduje wszystkie pięciocyfrowe liczby w ciągu. Uwaga // użycie symboli w tym przykładzie \\ var zipcode = new RegExp("\\d(5)", "g");

Konstruktor RegExp() jest przydatny, gdy wyrażenie regularne jest generowane dynamicznie i dlatego nie można go przedstawić za pomocą składni literału wyrażenia regularnego. Na przykład, aby znaleźć ciąg wprowadzony przez użytkownika, należy utworzyć wyrażenie regularne w czasie wykonywania za pomocą RegExp().

Właściwości RegExp

Każdy obiekt RegExp ma pięć właściwości. Nieruchomość źródło- ciąg znaków tylko do odczytu zawierający tekst wyrażenia regularnego. Nieruchomość światowy jest wartością logiczną tylko do odczytu, która określa, czy w wyrażeniu regularnym występuje flaga g. Nieruchomość zignorować przypadek to wartość logiczna przeznaczona tylko do odczytu, która określa, czy w wyrażeniu regularnym występuje flaga i. Nieruchomość multilinia jest wartością logiczną tylko do odczytu, która określa, czy w wyrażeniu regularnym występuje flaga m. I ostatnia właściwość ostatniindeks jest liczbą całkowitą, którą można czytać i zapisywać. Dla wzorców z flagą g ta właściwość zawiera numer pozycji w wierszu, od której powinno rozpocząć się kolejne wyszukiwanie. Jak opisano poniżej, jest ona używana przez metody exec() i test().

Metody RegExp

Obiekty RegExp definiują dwie metody dopasowujące wzorce; zachowują się podobnie do metod klasy String opisanych powyżej. Główną metodą klasy RegExp używaną do dopasowywania wzorców jest wykonanie(). Jest ona podobna do wspomnianej wcześniej metody match() klasy String, z tą różnicą, że jest to metoda klasy RegExp, która przyjmuje ciąg znaków jako argument, a nie metoda klasy String, która przyjmuje argument RegExp.

Metoda exec() wykonuje wyrażenie regularne dla określonego ciągu, tj. szuka dopasowania w ciągu. Jeśli nie zostanie znalezione żadne dopasowanie, metoda zwraca wartość null. Jeśli jednak zostanie znalezione dopasowanie, zwraca tę samą tablicę, co tablica zwrócona przez metodę match() do wyszukiwania bez flagi g. Element zerowy tablicy zawiera ciąg pasujący do wyrażenia regularnego, a wszystkie kolejne elementy zawierają podciągi pasujące do wszystkich podwyrażeń. Poza tym nieruchomość indeks zawiera numer pozycji znaku, od którego zaczyna się odpowiedni fragment, oraz właściwość wejście odnosi się do przeszukiwanej linii.

W przeciwieństwie do match() metoda exec() zwraca tablicę, której struktura nie zależy od obecności flagi g w wyrażeniu regularnym. Przypomnę, że przekazując globalne wyrażenie regularne, metoda match() zwraca tablicę znalezionych dopasowań. Funkcja exec() zawsze zwraca jedno dopasowanie, ale dostarcza o nim informacji pełna informacja. Kiedy funkcja exec() jest wywoływana w wyrażeniu regularnym zawierającym flagę g, metoda ustawia właściwość lastIndex obiektu wyrażenia regularnego na numer pozycji znaku znajdującego się bezpośrednio po znalezionym podciągu.

Kiedy funkcja exec() jest wywoływana po raz drugi w tym samym wyrażeniu regularnym, rozpoczyna wyszukiwanie od znaku, którego pozycja jest określona we właściwości lastIndex. Jeśli exec() nie znajdzie dopasowania, właściwość lastIndex zostaje ustawiona na 0. (Możesz także w dowolnej chwili ustawić lastIndex na zero, co należy zrobić we wszystkich przypadkach, gdy wyszukiwanie kończy się przed ostatnim dopasowaniem w pojedynczym wierszu znaleziono, a wyszukiwanie rozpoczyna się w innej linii z tym samym obiektem RegExp.) To specjalne zachowanie pozwala na wielokrotne wywoływanie funkcji exec() w celu iteracji po wszystkich dopasowaniach wyrażenia regularnego w linii. Na przykład:

Wzór Var = /Java/g; var tekst = "JavaScript jest ciekawszy niż Java!"; var wynik; while((result = wzór.exec(tekst)) != null) ( console.log("Znalezione "" + wynik + """ + " w pozycji " + wynik.indeks + "; następne wyszukiwanie rozpocznie się od " + wzór .lastIndex); )

Inną metodą obiektu RegExp jest test(), czyli dużo prostsza metoda wykonanie(). Pobiera ciąg znaków i zwraca wartość true, jeśli ciąg pasuje do wyrażenia regularnego:

Wzorzec Var = /Java/i; wzór.test("JavaScript"); // Zwróć wartość true

Wywołanie funkcji test() jest równoznaczne z wywołaniem funkcji exec(), która zwraca wartość true, jeśli funkcja exec() zwraca wartość inną niż null. Z tego powodu metoda test() zachowuje się w taki sam sposób jak metoda exec() po wywołaniu globalnego wyrażenia regularnego: rozpoczyna wyszukiwanie określonego ciągu od pozycji określonej przez właściwość lastIndex i jeśli znajdzie dopasowanie , ustawia właściwość lastIndex na numer pozycji znaku bezpośrednio obok znalezionego dopasowania. Dlatego za pomocą metody test() można utworzyć pętlę przejścia linii w taki sam sposób, jak przy użyciu metody exec().

W JavaScript wyrażenia regularne są reprezentowane przez obiekty RegExp. Obiekty RegExp można tworzyć za pomocą konstruktora RegExp(), ale częściej tworzy się je przy użyciu specjalnej składni dosłownej. Podobnie jak literały łańcuchowe są określane jako znaki ujęte w cudzysłów, tak literały wyrażeń regularnych są określane jako znaki ujęte w parę ukośników / .

/pattern/flags nowy RegExp("wzorzec"[, opcje wyszukiwania])

wzór- wyrażenie regularne do wyszukiwania (więcej o zamianie później) oraz flagi - ciąg dowolnej kombinacji znaków g (wyszukiwanie globalne), i (wielkość liter nie ma znaczenia) i m (wyszukiwanie wielowierszowe). Pierwszą metodę stosuje się często, drugą - czasami. Na przykład dwa takie wywołania są równoważne.

opcje wyszukiwania

Tworząc wyrażenie regularne, możemy określić dodatkowe opcje wyszukiwania

Znaki w wyrażeniach regularnych JavaScript

SymbolKorespondencja
Znaki alfanumeryczneOdpowiadają sobie
\0 Znak NUL (\u0000)
\TZakładka (\u0009)
\NPrzesunięcie wiersza (\u000A)
\vZakładka pionowa (\u000B)
\FTłumaczenie strony (\u000C)
\RPowrót przewozu (\u000D)
\xnnZnak ze zbioru łacińskiego, określony liczbą szesnastkową nn; na przykład \x0A jest tym samym, co \n
\xxxxxZnak Unicode określony liczbą szesnastkową xxxx; na przykład \u0009 jest tym samym, co \t
\cXZnak kontrolny „X”, na przykład sekwencja \cJ, jest równoważna znakowi nowej linii \n
\ Dla zwykłych postaci - czyni je wyjątkowymi. Na przykład wyrażenie /s/ po prostu szuka znaku „s”. A jeśli umieścisz \ przed s, to /\s/ już oznacza znak spacji i odwrotnie, jeśli znak jest specjalny, na przykład *, wówczas \ sprawi, że będzie to zwykły znak „gwiazdki”. Na przykład /a*/ wyszukuje 0 lub więcej kolejnych znaków „a”. Aby znaleźć gwiazdkę „a*” - wstaw \ przed znakiem specjalnym. symbol: /a\*/ .
^ Wskazuje początek danych wejściowych. Jeśli ustawiona jest flaga wyszukiwania wielowierszowego („m”), zostanie ona uruchomiona również na początku nowej linii. Na przykład /^A/ nie znajdzie „A” w „A”, ale znajdzie pierwszą „A” w „An A”.
$ Wskazuje koniec danych wejściowych. Jeśli ustawiona jest flaga wyszukiwania wielowierszowego, będzie ona działać również na końcu linii, np. /t$/ nie znajdzie „t” w „eater”, ale znajdzie je w „eat”.
* Wskazuje powtórzenie 0 lub więcej razy. Na przykład /bo*/ znajdzie „boooo” w „A Ghost Buu” i „b” w „A Bird Warbled”, ale nie znajdzie niczego w „A Goat Chrząknięcie”.
+ Wskazuje powtórzenie 1 lub więcej razy. Odpowiednik (1,). Na przykład /a+/ dopasuje „a” w „cukierkach” i całe „a” w „caaaaaaandy”.
? Wskazuje, że element może występować lub nie. Na przykład /e?le?/ dopasuje „el” w „anioł” i „le” w „kąt”. Jeśli zostanie użyte bezpośrednio po jednym z kwantyfikatorów * , + , ? lub () , następnie określa wyszukiwanie „nie zachłanne” (powtarzanie minimalnej możliwej liczby razy do najbliższego następnego elementu wzorca), w przeciwieństwie do domyślnego trybu „zachłannego”, który maksymalizuje liczbę powtórzeń, nawet jeśli następny element wzorca również pasuje.. Dodatkowo ? użyte w podglądzie, które opisano w tabeli pod (?=) , (?!) i (?:) .
. (Przecinek dziesiętny) reprezentuje dowolny znak inny niż znak nowej linii: \n \r \u2028 lub \u2029. (możesz użyć [\s\S], aby wyszukać dowolny znak, łącznie ze znakami nowej linii). Na przykład /.n/ dopasuje „an” i „on” w wyrażeniu „nie, jabłko jest na drzewie”, ale nie „nie”.
(X)Znajduje x i pamięta. Nazywa się to „nawiasami pamięci”. Na przykład /(foo)/ znajdzie i zapamięta „foo” w „foo bar”. Znaleziony podciąg zapisywany jest w tablicy wyników wyszukiwania lub we predefiniowanych właściwościach obiektu RegExp: $1, ..., $9. Dodatkowo nawiasy łączą to, co jest w nich zawarte, w jeden element wzorca. Na przykład (abc)* - powtórz abc 0 lub więcej razy.
(?:X)Znajduje x, ale nie pamięta, co znalazło. Nazywa się to „nawiasami pamięci”. Znaleziony podciąg nie jest przechowywany w tablicy wyników ani we właściwościach RegExp.Podobnie jak wszystkie nawiasy, łączą one zawartość w jeden podwzorzec.
x(?=y)Znajduje x tylko wtedy, gdy po x następuje y. Na przykład /Jack(?=Sprat)/ dopasuje słowo „Jack” tylko wtedy, gdy następuje po nim „Szprot”. /Jack(?=Sprat|Frost)/ dopasuje „Jack” tylko wtedy, gdy następuje po nim „Sprat” lub „Frost”. Jednak w wynikach wyszukiwania nie pojawi się ani „Sprat”, ani „Frost”.
x(?!y)Znajduje x tylko wtedy, gdy po x nie następuje y. Na przykład /\d+(?!\.)/ dopasuje liczbę tylko wtedy, gdy nie nastąpi po niej przecinek dziesiętny. /\d+(?!\.)/.exec("3.141") znajdzie 141, ale nie 3.141.
x|yZnajduje x lub y. Na przykład /green|red/ dopasuje „zielony” do „zielonego jabłka” i „czerwony” do „czerwonego jabłka”.
(N)Gdzie n jest dodatnią liczbą całkowitą. Znajduje dokładnie n powtórzeń poprzedniego elementu. Na przykład /a(2)/ nie znajdzie „a” w „candy”, ale znajdzie zarówno a w „caandy”, jak i pierwsze dwa a w „caaandy”.
(N,)Gdzie n jest dodatnią liczbą całkowitą. Znajduje n lub więcej powtórzeń elementu. Na przykład /a(2,) nie znajdzie „a” w „candy”, ale znajdzie całe „a” w „caandy” i „caaaaaandy”.
(n, m)Gdzie n i m są dodatnimi liczbami całkowitymi. Znajdź od n do m powtórzeń elementu.
Zestaw znaków. Znajduje dowolny z wymienionych znaków. Odstępy można wskazać za pomocą myślnika. Na przykład - to samo co . Dopasowuje „b” w „mostku” oraz „a” i „c” w „ból”.
[^xyz]Dowolny znak inny niż określony w zestawie. Można także określić rozpiętość. Na przykład [^abc] jest tym samym, co [^a-c] . Znajduje „r” w „mostku” i „h” w „chop”.
[\B]Znajduje znak Backspace. (Nie mylić z \b .)
\BZnajduje (łacińską) granicę słowa, na przykład spację. (Nie mylić z [\b]). Na przykład /\bn\w/ dopasuje „nie” w „południu”; /\wy\b/ znajdzie „ly” w „prawdopodobnie wczoraj”.
\BNie wyznacza granicy słów. Na przykład /\w\Bn/ dopasuje „on” w „południu”, a /y\B\w/ dopasuje „ye” w „prawdopodobnie wczoraj”.
\cXGdzie X jest literą od A do Z. Wskazuje znak kontrolny w ciągu. Na przykład /\cM/ reprezentuje znak Ctrl-M.
\Dznajduje liczbę z dowolnego alfabetu (nasz to Unicode). Użyj, aby znaleźć tylko zwykłe liczby. Na przykład /\d/ lub // dopasuje „2” w „B2 to numer apartamentu”.
\DZnajduje znak inny niż numeryczny (wszystkie alfabety). [^0-9] jest odpowiednikiem zwykłych liczb. Na przykład /\D/ lub /[^0-9]/ dopasuje „B” w „B2 to numer pakietu”.
\SZnajduje dowolny biały znak, w tym spację, tabulator, znak nowej linii i inne białe znaki Unicode. Na przykład /\s\w*/ dopasuje „bar” w „foo bar”.
\SZnajduje dowolny znak z wyjątkiem białych znaków. Na przykład /\S\w*/ dopasuje „foo” w „foo bar”.
\vPionowy znak tabulacji.
\wZnajduje dowolny znak słowa (alfabetu łacińskiego), w tym litery, cyfry i znaki podkreślenia. Równowartość. Na przykład /\w/ dopasuje „a” do „jabłko”, „5” do „5,28 USD” i „3” do „3D”.
\WZnajduje dowolny znak słowny inny niż (łaciński). Odpowiednik [^A-Za-z0-9_] . Na przykład /\W/ i /[^$A-Za-z0-9_]/ będą w równym stopniu pasować do „%” w „50%”.

Praca z wyrażeniami regularnymi w JavaScript

Praca z wyrażeniami regularnymi w JavaScript jest realizowana za pomocą metod klasy String

exec(regexp) - znajduje wszystkie dopasowania (wpisy w zwykłym wzorcu) w ciągu znaków. Zwraca tablicę (jeśli istnieje dopasowanie) i aktualizuje właściwość regexp lub null, jeśli nic nie zostanie znalezione. Z modyfikatorem g - za każdym razem, gdy funkcja ta zostanie wywołana, zwróci ona następne dopasowanie po poprzednim znalezionym - jest to realizowane poprzez zachowanie indeksu przesunięcia ostatniego wyszukiwania.

match(regexp) - znajdź część ciągu używając wzorca. Jeśli podano modyfikator g, funkcja match() zwraca tablicę zawierającą wszystkie dopasowania lub wartość null (zamiast pustej tablicy). Bez modyfikatora g ta funkcja działa jak exec();

test(regexp) - funkcja sprawdza dopasowanie ciągu znaków do wzorca. Zwraca wartość true, jeśli istnieje dopasowanie, i false, jeśli nie ma dopasowania.

split(regexp) — Dzieli ciąg, do którego jest wywoływany, na tablicę podciągów, używając argumentu jako ogranicznika.

zamień(regexp, mix) - metoda zwraca zmodyfikowany ciąg znaków zgodnie z szablonem (wyrażenie regularne). Pierwszym parametrem wyrażenia regularnego może być także ciąg znaków, a nie wyrażenie regularne. Bez modyfikatora g metoda w wierszu zastępuje tylko pierwsze wystąpienie; z modyfikatorem g - następuje globalna zamiana, tj. wszystkie wystąpienia w danej linii ulegają zmianie. mix - szablon zastępczy, może przyjąć wartości stringu, szablon zastępczy, funkcję (nazwę funkcji).

Znaki specjalne w ciągu zastępczym

Wymiana poprzez funkcję

Jeśli jako drugi parametr określisz funkcję, zostanie ona wykonana przy każdym dopasowaniu. Funkcja może dynamicznie generować i zwracać ciąg podstawieniowy. Pierwszym parametrem funkcji jest znaleziony podciąg. Jeśli pierwszym argumentem do zastąpienia jest obiekt RegExp, wówczas kolejnych n parametrów zawiera dopasowania w zagnieżdżonych nawiasach. Ostatnie dwa parametry to pozycja w wierszu, w którym nastąpiło dopasowanie, oraz sama linia.