O ile wiem, nie ma czegoś takiego jak nazwane grupy przechwytywania w JavaScript. Jaki jest alternatywny sposób uzyskania podobnej funkcjonalności?
javascript
regex
mmierins
źródło
źródło
Odpowiedzi:
ECMAScript 2018 wprowadza nazwane grupy przechwytywania do wyrażeń regularnych JavaScript.
Przykład:
Jeśli potrzebujesz obsługi starszych przeglądarek, możesz zrobić wszystko z normalnymi (numerowanymi) grupami przechwytywania, co możesz zrobić z nazwanymi grupami przechwytywania, wystarczy śledzić liczby - co może być kłopotliwe, jeśli kolejność przechwytywania grupy w twojej regex zmiany.
Są tylko dwie „strukturalne” zalety nazwanych grup przechwytywania, o których mogę myśleć:
W niektórych odmianach wyrażeń regularnych (.NET i JGSoft, o ile wiem) możesz używać tej samej nazwy dla różnych grup w swoim wyrażeniu regularnym ( zobacz tutaj, gdzie to ma znaczenie ). Ale większość smaków wyrażeń regularnych i tak nie obsługuje tej funkcji.
Jeśli potrzebujesz odwoływać się do numerowanych grup przechwytywania w sytuacji, gdy są otoczone cyframi, możesz mieć problem. Powiedzmy, że chcesz dodać zero do cyfry i dlatego chce wymienić
(\d)
z$10
. W JavaScript to zadziała (pod warunkiem, że masz mniej niż 10 grup przechwytujących w wyrażeniu regularnym), ale Perl pomyśli, że szukasz numeru referencji10
zamiast numeru1
, po którym następuje0
. W Perlu możesz użyć${1}0
w tym przypadku.Poza tym, nazwane grupy przechwytujące to po prostu „cukier składniowy”. Pomaga używać grup przechwytywania tylko wtedy, gdy naprawdę ich potrzebujesz i używać grup nie przechwytujących
(?:...)
we wszystkich innych okolicznościach.Większy problem (moim zdaniem) z JavaScriptem polega na tym, że nie obsługuje pełnych wyrażeń regularnych, co znacznie ułatwiłoby tworzenie czytelnych, złożonych wyrażeń regularnych.
Biblioteka XRegExp Steve'a Levithana rozwiązuje te problemy.
źródło
Możesz użyć XRegExp , rozszerzonej, rozszerzalnej implementacji wyrażeń regularnych w różnych przeglądarkach, w tym obsługi dodatkowej składni, flag i metod:
s
wyrażeń regularnych:, aby kropka pasowała do wszystkich znaków (inaczej tryb dotall lub singleline), orazx
, dla wolnych odstępów i komentarzy (aka tryb rozszerzony).źródło
Inne możliwe rozwiązanie: utwórz obiekt zawierający nazwy grup i indeksy.
Następnie użyj kluczy obiektu, aby odnieść się do grup:
Poprawia to czytelność / jakość kodu przy użyciu wyników wyrażenia regularnego, ale nie czytelność samego wyrażenia regularnego.
źródło
W ES6 możesz użyć restrukturyzacji tablic, aby złapać swoje grupy:
Ogłoszenie:
let
pomija pierwszą wartość wynikowej tablicy, czyli cały dopasowany ciąg|| []
po.exec()
zapobiegnie destructuring błąd, gdy nie znaleziono żadnego meczu (bo.exec()
wrócinull
)źródło
String.prototype.match
zwraca tablicę z: całym dopasowanym łańcuchem w pozycji 0, a następnie dowolnymi grupami po tym. Pierwszy przecinek mówi „pomiń element w pozycji 0”RegExp.prototype.exec
przejęciaString.prototype.match
w miejscach, gdzie mogą być łańcuchnull
lubundefined
.Aktualizacja: w końcu został włączony do JavaScript (ECMAScript 2018)!
Nazwane grupy przechwytujące mogą wkrótce znaleźć się w JavaScript.
Propozycja jest już na etapie 3.
Grupie przechwytywania można nadać nazwę w nawiasach kątowych za pomocą
(?<name>...)
składni dla dowolnej nazwy identyfikatora. Wyrażenie regularne dla daty można następnie zapisać jako/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u
. Każda nazwa powinna być unikalna i zgodna z gramatyką dla ECMAScript IdentifierName .Dostęp do nazwanych grup można uzyskać z właściwości właściwości grup wyniku wyrażenia regularnego. Tworzone są również numerowane odniesienia do grup, tak jak w przypadku grup nienazwanych. Na przykład:
źródło
let {year, month, day} = ((result) => ((result) ? result.groups : {}))(re.exec('2015-01-02'));
Nazewnictwo przechwyconych grup zapewnia jedną rzecz: mniej zamieszania ze złożonymi wyrażeniami regularnymi.
To naprawdę zależy od przypadku użycia, ale być może ładne wydrukowanie wyrażenia regularnego może pomóc.
Możesz też spróbować zdefiniować stałe w celu odniesienia do przechwyconych grup.
Komentarze mogą wtedy również pomóc pokazać innym, którzy czytają Twój kod, co zrobiłeś.
Co do reszty, muszę zgodzić się z odpowiedzią Tims.
źródło
Istnieje biblioteka node.js o nazwie named-regexp , której można użyć w projektach node.js (włączonej w przeglądarce, pakując bibliotekę w przeglądarkę lub inne skrypty do pakowania). Jednak biblioteki nie można używać z wyrażeniami regularnymi, które zawierają niewymienione grupy przechwytujące.
Jeśli policzysz otwierające nawiasy klamrowe w wyrażeniu regularnym, możesz utworzyć odwzorowanie między nazwanymi grupami przechwytującymi a ponumerowanymi grupami przechwytującymi w wyrażeniu regularnym i możesz dowolnie mieszać i dopasowywać. Musisz tylko usunąć nazwy grup przed użyciem wyrażenia regularnego. Napisałem trzy funkcje, które to pokazują. Zobacz tę treść: https://gist.github.com/gbirke/2cc2370135b665eee3ef
źródło
Jak powiedział Tim Pietzcker , ECMAScript 2018 wprowadza nazwane grupy przechwytywania do wyrażeń regularnych JavaScript. Ale w powyższych odpowiedziach nie znalazłem sposobu użycia nazwanej przechwyconej grupy w samym wyrażeniu regularnym.
można użyć nazwie przechwycony grupę z tej składni:
\k<name>
. na przykładi jak powiedział Forivin , możesz użyć przechwyconej grupy w wyniku obiektu w następujący sposób:
źródło
Chociaż nie możesz tego zrobić za pomocą waniliowego JavaScript, być może możesz użyć
Array.prototype
funkcji, takiej jakArray.prototype.reduce
zamienianie indeksowanych dopasowań w nazwane przy użyciu magii .Oczywiście następujące rozwiązanie będzie wymagało, aby dopasowania występowały w kolejności:
źródło
var assocArray = Regex("hello alex, I am dennis", "hello ({hisName}.+), I am ({yourName}.+)");
RegExp
obiekt, dodając funkcję do jego prototypu.Nie masz ECMAScript 2018?
Moim celem było, aby działał jak najbardziej zbliżony do tego, do czego jesteśmy przyzwyczajeni z nazwanymi grupami. Podczas gdy w ECMAScript 2018 możesz umieścić
?<groupname>
wewnątrz grupy, aby wskazać nazwaną grupę, w moim rozwiązaniu dla starszego javascript możesz umieścić(?!=<groupname>)
wewnątrz grupy, aby zrobić to samo. Jest to więc dodatkowy zestaw nawiasów i dodatkowy!=
. Całkiem blisko!Owinęłam to wszystko w funkcję prototypu łańcucha
cechy
Instrukcje
(?!={groupname})
w każdej grupie, którą chcesz nazwać()
których nie udało się przechwycić, umieszczając je?:
na początku tej grupy. Nie zostaną nazwane.arrays.js
stosowanie
wynik o
źródło