Jak mogę używać wyrażeń regularnych obsługujących Unicode w JavaScript?
Na przykład powinno być coś podobnego, \w
co może pasować do dowolnego punktu kodowego w kategorii Litery lub Znaki (nie tylko ASCII), i mam nadzieję, że mają filtry takie jak [[P *]] do interpunkcji itp.
javascript
regex
unicode
character-properties
Peter Mortensen
źródło
źródło
Odpowiedzi:
Sytuacja dla ES 6
Nadchodząca specyfikacja języka ECMAScript, wydanie 6, zawiera wyrażenia regularne obsługujące Unicode. Obsługa musi być włączona za pomocą
u
modyfikatora wyrażenia regularnego. Zobacz wyrażenia regularne obsługujące Unicode w ES6 .Jednak dopóki ES 6 nie zostanie ukończony i nie zostanie powszechnie przyjęty przez producentów przeglądarek, nadal jesteś sam. Aktualizacja: Dostępny jest teraz transpiler o nazwie regexpu, który tłumaczy wyrażenia regularne Unicode ES6 na równoważne ES5. Może być używany jako część procesu kompilacji. Wypróbuj online.
Sytuacja dla ES 5 i niższych
Mimo że JavaScript działa na ciągach znaków Unicode, nie implementuje klas znaków obsługujących Unicode i nie ma pojęcia o klasach znaków POSIX ani blokach / podzakresach Unicode.
Problemy z Unicode w wyrażeniach regularnych JavaScript
Sprawdź swoje oczekiwania tutaj: Tester JavaScript RegExp Unicode Character Class ( Edytuj: oryginalna strona nie działa, archiwum internetowe wciąż ma kopię .)
Flagrant Badassery ma artykuł na temat JavaScript, Regex i Unicode, który rzuca nieco światła na tę sprawę.
Przeczytaj także Regex i Unicode tutaj na SO. Prawdopodobnie musisz zbudować własną „klasę znaków interpunkcyjnych”.
Sprawdź Wyrażenie regularne: Dopasuj konstruktor zakresu bloków Unicode , który pozwala zbudować wyrażenie regularne JavaScript, które pasuje do znaków należących do dowolnej liczby określonych bloków Unicode.
Zrobiłem to dla podzakresów „Ogólna interpunkcja” i „Dodatkowa interpunkcja”, a wynik jest tak prosty i bezpośredni, jak bym się spodziewał:
Istnieje również XRegExp , projekt, który zapewnia obsługę Unicode w JavaScript , oferując alternatywny silnik regex z rozszerzonymi możliwościami.
I oczywiście wymagana lektura: mathiasbynens.be - JavaScript ma problem z Unicode :
źródło
u
banderą, jak również niektóre inne ES6 wyposażony do pracy z Unicode.u
wyrażeń regularnych."a品cd!e f".replace(/[^\w]/ug, "")
ale wynikowe wyrażenie regularne (działające w Chrome 59) wciąż usuwa品
postać i powraca"acdef"
Osobiście wolałbym nie instalować innej biblioteki tylko po to, aby uzyskać tę funkcjonalność. Moja odpowiedź nie wymaga żadnych zewnętrznych bibliotek i może również działać z niewielkimi modyfikacjami smaków regex oprócz JavaScript.
Strona internetowa Unicode zapewnia sposób na przetłumaczenie kategorii Unicode na zestaw punktów kodowych. Ponieważ jest to strona internetowa Unicode , informacje z niej powinny być dokładne.
Pamiętaj, że musisz wykluczyć znaki wysokiej klasy, ponieważ JavaScript obsługuje tylko znaki mniejsze niż
FFFF
(hex). Sugeruję zaznaczenie pól wyboru Skróć sortowanie i Escape, które zapewniają równowagę między unikaniem znaków niedrukowalnych a minimalizacją rozmiaru wyrażenia regularnego.Oto kilka typowych rozszerzeń różnych właściwości Unicode:
\p{L}
(Litery):\p{Nd}
(Liczba cyfr dziesiętnych):\p{P}
(Interpunkcja):Strona rozpoznaje również szereg niejasnych klas znaków, takich jak
\p{Hira}
, które są po prostu (japońskimi) znakami Hiragana:Wreszcie, możliwe jest podłączenie klasy char z więcej niż jedną właściwością Unicode, aby uzyskać krótsze wyrażenie regularne niż po prostu przez ich połączenie (o ile pewne ustawienia są sprawdzone).
źródło
\p
-Syntax wydaje się nie działać w JS,/\p{L}/.test('a')
jestfalse
Nie znajdując też dobrego rozwiązania, już dawno napisałem mały skrypt , pobierając dane ze specyfikacji Unicode (v.5.0.0) i generując przedziały dla każdej kategorii i podkategorii w BMP (ostatnio zastąpione małym Program Java, który korzysta z własnej natywnej obsługi Unicode).
Zasadniczo konwertuje
\p{...}
na zakres wartości, podobnie jak dane wyjściowe narzędzia wspomnianego przez Tomalaka, ale interwały mogą być dość duże (ponieważ nie dotyczy to bloków, ale znaków rozproszonych po wielu różnych miejscach).Na przykład Regex napisany w ten sposób:
Zostanie przekonwertowany na coś takiego:
Nie używałem go zbyt często w praktyce, ale wydaje się, że działa dobrze z moich testów, więc piszę tutaj na wypadek, gdyby ktoś uznał to za przydatne. Pomimo długości wynikowych wyrażeń regularnych (powyższy przykład ma 3591 znaków po rozwinięciu), wydajność wydaje się być do zaakceptowania (zobacz testy w jsFiddle; dzięki @modiX i @Lwangaman za ulepszenia).
Oto źródło (RAW, 27.5KB; minified , 24.9KB, nie wiele lepiej ...). To może być mniejsza o unescaping znaki Unicode, ale OTOH będzie ryzykujemy kwestii kodowania, więc odchodzę, jak jest. Mam nadzieję, że dzięki ES6 tego typu rzeczy nie będą już potrzebne.
Aktualizacja : wygląda to tak samo jak strategia zastosowana we wtyczce XRegExp Unicode wspomnianej przez Tim Down, z tym wyjątkiem, że w tym przypadku używane są regularne wyrażenia regularne JavaScript.
źródło
/^\p{L}+$/
powinno pasować,東海林
ale tak nie jest. Po każdej aktualizacji kolekcji proszę o informację. Wielkie dzięki.\p{Lo}
, brakuje w niej obu tabel Kanji.Jak wspomniano w innych odpowiedziach, wyrażenia regularne JavaScript nie obsługują klas znaków Unicode. Istnieje jednak biblioteka, która to zapewnia: doskonały XRegExp Stevena Levithana i jego wtyczka Unicode .
źródło
[^\u0000-\u007F]+
dla dowolnych znaków, które nie zawierają znaków ASCII.Na przykład:
Oto kilka doskonałych referencji:
Generator RegExp zakresu Unicode
Wyrażenia regularne Unicode
Tabele kodów znaków Unicode 10.0
Dopasuj zakres bloków Unicode
źródło
Wrzesień 2018 (zaktualizowany luty 2019)
Wygląda na to, że wyrażenie regularne
/\p{L}/u
dla liter dopasowania (jako kategorii Unicode )Oto działający przykład
Zgłaszam ten błąd tutaj .
Aktualizacja
Po ponad 2 latach zgodnie z: 1500035 > 1361876 > 1634135 wreszcie ten błąd został naprawiony i będzie dostępny w przeglądarce Firefox v.78 +
źródło
To zrobi to:
Wyraźnie wybiera zakres znaków Unicode. Będzie działać dla znaków łacińskich, ale inne dziwne postacie mogą znajdować się poza tym zakresem.
źródło
\u0100
i\u0280
: wiele z nich można uznać za znaki łacińskie, ale inne nie: var s = ''; for (var i = 0xFF; i <= 0x280; i ++) {s + = String.fromCharCode (i)} "ÿĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏ ... ǐǑǒǓǔǕǖǗǘǙǚǛǜǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZDzdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗŞşŢţȜȝȞȟȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɂɃɄɅɆɇɈɉɊɋɌɍɎɏɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀ"W JavaScript, \ wi id to ASCII, a \ s to Unicode. Nie pytaj mnie dlaczego. JavaScript obsługuje \ p z kategoriami Unicode, których można użyć do emulacji \ wi i \ d obsługujących Unicode.
Do \ d użyj \ p {N} (cyfry)
Do \ w użyj [\ p {L} \ p {N} \ p {Pc} \ p {M}] (litery, cyfry, podkreślenia, znaki)
Aktualizacja: Niestety, myliłem się co do tego. JavaScript też oficjalnie nie obsługuje \ p, chociaż niektóre implementacje mogą nadal to obsługiwać. Jedyną obsługą Unicode w wyrażeniach regularnych JavaScript jest dopasowanie określonych punktów kodowych do \ uFFFF. Możesz używać ich w zakresach w klasach postaci.
źródło
/\p{L}+/u
Jeśli używasz Babel następnie wsparcie Unicode jest już dostępny.
Wydałem również wtyczkę, która przekształca kod źródłowy, dzięki czemu możesz pisać wyrażenia regularne, takie jak
/^\p{L}+$/
. Zostaną one następnie przekształcone w coś, co zrozumieją przeglądarki.Oto strona projektu wtyczki:
babel-plugin-utf-8-regex
źródło
Odpowiadam na to pytanie.
Jaki byłby odpowiednik dla \ p {Lu} lub \ p {Ll} w regExp dla js?
ponieważ został oznaczony jako dokładna kopia aktualnego starego pytania.
Przeszukując bazę danych UCD Unicode 12, \ p {Lu} generuje 1788 punktów kodowych.
Konwersja na UTF-16 daje równoważność konstruktu klasy.
Jest to ciąg znaków o długości 4k i można go łatwo wykonać w dowolnych silnikach wyrażeń regularnych.
Przeszukując bazę danych UCD Unicode 12, \ p {Ll} generuje 2151 punktów kodowych.
Konwersja na UTF-16 daje równoważność konstruktu klasy.
Zauważ, że implementacja wyrażenia regularnego \ p {Lu} lub \ p {Pl} faktycznie wywołuje a
niestandardową funkcję w celu przetestowania wartości.
Pokazane tutaj klasy postaci są wykonywane inaczej i są liniowe, standardowe
i dość powolne, gdy są zablokowane głównie w jednej klasie.
Pewien wgląd w to, jak silnik Regex (ogólnie) implementuje klasy właściwości Unicode:
Sprawdź te cechy wydajnościowe między właściwością
a blokiem klasy (jak wyżej)
Wow, co za różnica !!
Zobaczmy, jak można wdrożyć właściwości
Tablica wskaźników [10FFFF], gdzie każdy indeks jest kodem
Każdy wskaźnik w tablicy ma strukturę klasyfikacji.
Struktura klasyfikacji zawiera stałe elementy pola.
Niektóre mają wartość NULL i nie dotyczą.
Niektóre zawierają klasyfikacje kategorii.
Przykład: kategoria ogólna
Jest to element mapy bitowej, który wykorzystuje 17 z 64 bitów.
Cokolwiek obsługuje ten punkt kodowy, bit (y) są ustawione jako maska.
-Close_Punctuation
-Connector_Punctuation
-Control
-Currency_Symbol
-Dash_Punctuation
-Decimal_Number
-Enclosing_Mark
-Final_Punctuation
-format
-Initial_Punctuation
-Letter_Number
-Line_Separator
-Lowercase_Letter
-Math_Symbol
-Modifier_Letter
-Modifier_Symbol
-Nonspacing_Mark
-Open_Punctuation
-Other_Letter
-Other_Number
-Other_Punctuation
-Other_Symbol
-Paragraph_Separator
-Private_Use
-Space_Separator -Zastępcza
-Spacing_Mark
-Titlecase_Letter
-Unassigned
-Uppercase_Letter
Kiedy wyrażenie regularne jest analizowane z czymś takim jak ten \ p {Lu},
jest ono tłumaczone bezpośrednio na
Kolejny przykład, gdy wyrażenie regularne jest analizowane z właściwością interpunkcyjną \ p {P},
jest tłumaczone na
Kontrola tego elementu dla dowolnego z tych bitów elementów, które są połączone w maskę:
-Close_Punctuation
-Connector_Punctuation
-Dash_Punctuation
-Final_Punctuation
-Initial_Punctuation
-Open_Punctuation
-Other_Punctuation
Przesunięcie i bit lub bit (maska) są przechowywane jako krok wyrażenia regularnego dla tej właściwości.
Tabela odnośników jest tworzona raz dla wszystkich punktów kodowych Unicode korzystających z tej tablicy.
Kiedy znak jest zaznaczony, jest to tak proste, jak użycie CP jako indeksu w tej tablicy i sprawdzenie określonego elementu struktury klasyfikacji dla tego bitu (maski).
Ta struktura jest rozszerzalna i pośrednia, aby zapewnić znacznie bardziej złożone wyszukiwania. To tylko prosty przykład.
Porównaj to wyszukiwanie bezpośrednie z wyszukiwaniem klas znaków:
Wszystkie klasy są liniową listą pozycji wyszukiwanych od lewej do prawej.
W tym porównaniu, biorąc pod uwagę, że nasz ciąg docelowy zawiera tylko kompletne wielkie litery Unicode, prawo średnich przewidywałoby, że połowa elementów w klasie musiałaby zostać sprawdzona na odległość, aby znaleźć dopasowanie.
Jest to ogromna wada wydajności.
Jeśli jednak tabele odnośników nie istnieją lub nie są aktualne w najnowszej wersji Unicode (12 od tej daty),
byłby to jedyny sposób.
W rzeczywistości jest to w większości jedyny sposób na uzyskanie kompletnych
znaków Emoji, ponieważ nie ma określonej właściwości (ani uzasadnienia) do ich przypisania.
źródło
Możesz także użyć:
źródło