Бетонний Jage Regex для наголошених персонажів (діакритики)


166

Я дивився на переповнення стека ( замінюючи символи .. е , як JavaScript не відповідає стандарту Unicode щодо RegExp тощо) і не знайшов конкретної відповіді на питання:

How can JavaScript match for accented characters (those with diacritical marks)?

Я змушую поле в інтерфейсі відповідати формату: last_name, first_name (останній [пробіл комами] спочатку) , і я хочу надати підтримку діакритики, але, очевидно, в JavaScript це трохи складніше, ніж в інших мовах / платформах.

Це була моя оригінальна версія, доки я не хотів додати діакритичну підтримку:

/^[a-zA-Z]+,\s[a-zA-Z]+$/

В даний час я обговорюю один з трьох методів додати підтримку, які я протестував і працюю (принаймні, певною мірою, я не знаю, що таке "ступінь" другого підходу). Ось вони:

Явно перелічуються всі наголошені символи, які я хотів би прийняти як дійсні (кульгаві та надмірно складні):


var accentedCharacters = "àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝâêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿÄËÏÖÜŸçÇßØøÅåÆæœ";
// Build the full regex
var regex = "^[a-zA-Z" + accentedCharacters + "]+,\\s[a-zA-Z" + accentedCharacters + "]+$";
// Create a RegExp from the string version
regexCompiled = new RegExp(regex);
// regexCompiled = /^[a-zA-ZàèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝâêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿÄËÏÖÜŸçÇßØøÅåÆæœ]+,\s[a-zA-ZàèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝâêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿÄËÏÖÜŸçÇßØøÅåÆæœ]+$/
  • Це правильно відповідає прізвище / ім’я будь-яким із підтримуваних наголошених символів у accentedCharacters.

Мій інший підхід полягав у використанні .класу символів, щоб мати простіший вираз:

var regex = /^.+,\s.+$/;
  • Цей матч буде просто ні про що, по крайней мере , в вигляді: something, something. Я гадаю, гаразд ...

Останній підхід, який я щойно знайшов, може бути простішим ...

/^[a-zA-Z\u00C0-\u017F]+,\s[a-zA-Z\u00C0-\u017F]+$/
  • Він відповідає ряду символів Unicode - перевірених і працюючих, хоча я не спробував нічого божевільного, просто звичайні речі, які я бачу в нашому мовному відділі щодо імен членів факультету.

Ось мої проблеми:

  1. Перше рішення є занадто обмежуючим, і неохайним і суворим. Це потрібно було б змінити, якби я забув персонажа чи двох, і це просто не дуже практично.
  2. Друге рішення краще, стисло, але воно, мабуть, відповідає набагато більше, ніж насправді повинно бути. Я не зміг знайти жодної реальної документації щодо того , що саме. відповідає, просто узагальнення "будь-якого символу, крім символу нової лінії" (з таблиці на MDN ).
  3. Третє рішення, здається, є найбільш точним, але чи є якісь голоси? Я не дуже знайомий з Unicode, принаймні на практиці, але дивлячись на кодову таблицю / продовження цієї таблиці , \u00C0-\u017Fздається, досить солідним, принаймні, на мій очікуваний вклад.

    • Факультет не надсилатиме форми з їх іменами рідною мовою (наприклад, арабською, китайською, японською тощо), тому мені не доведеться турбуватися про символи набору символів, які не є латинськими.

Тож справжнє питання : Який із цих трьох підходів найбільше підходить для виконання завдання? Або є кращі рішення?


1
Здається, немає особливих причин використовувати складніші виразки. Єдине, що стосується найпростішого рішення - воно також відповідатиме "щось, щось, щось". Ви можете використовувати щось подібне, regex = /^[^,]+,\s[^,]+$/;щоб запобігти цьому.
usr2564301

4
На перший погляд, перший не збігатиметься із загальною назвою "О'Доннелл, Кріс", ані зіставними прізвищами з дефісом, а також численними прізвищами тощо. Ознайомтеся з фальшивими програмістами, які вірять у імена майже для всіх можливих підводних каменів.
usr2564301

« Атом відповідає нічого , крім символів нового рядка » на насправді є досить точним :-).
Берги

1
Якщо ви можете скористатися додатковою бібліотекою, ви можете подивитися на мою відповідь тут
stema

Jongware, я фактично просто читав цю статтю, коли я переглядав ТАК, щоб відповісти на моє запитання - я також повністю забув про дефіси та апострофи тощо, я більше переймався тим, як зробити її першою міжнародною: P Я радий, що ти її приніс вгору, хоча! І Stema, я насправді переглянув цю бібліотеку, і я уникаю включення бібліотек, тому що це все в Google Apps Script - включення зовнішніх бібліотек було б кошмаром, і я використовував би його (у цьому випадку) лише для одного конкретного поля ... вид надмірності: P
Chris Cirefice

Відповіді:


275

Найпростіший спосіб прийняти всі акценти:

[A-zÀ-ú] // accepts lowercase and uppercase characters
[A-zÀ-ÿ] // as above but including letters with an umlaut (includes [ ] ^ \ × ÷)
[A-Za-zÀ-ÿ] // as above but not including [ ] ^ \
[A-Za-zÀ-ÖØ-öø-ÿ] // as above but not including [ ] ^ \ × ÷

Див. Https://unicode-table.com/en/ для символів, перелічених у числовому порядку.


2
Це добре працює, +1, але ви могли б пояснити, чому це працює?
П’єр Генрі

1
@PierreHenry -визначає діапазон, і ця методика використовує впорядкування символів у шафі, щоб визначити безперервний діапазон, роблячи надто стисле вирішення проблеми
Angad

8
не відповідає це підкреслення (та інші символи, що не містять слова, між Zі a)?
jcuenod

21
Це відповідає щонайменше символам [,], ^ і \, жоден з яких не повинен включатись.
Нейт

2
Не працює, кілька символів у цьому діапазоні не є наголошеними символами (наприклад, U + 00D7 - знак множення), дивіться це: unicode-table.com/uk
Jérémy Pouyet

39

Діапазон наголосів на латині \u00C0-\u017Fбув недостатньо для моєї бази даних імен, тому я розширив регулярний вираз

[a-zA-Z\u00C0-\u024F]
[a-zA-Z\u00C0-\u024F\u1E00-\u1EFF] // includes even more Latin chars

Я додав ці блоки коду ( \u00C0-\u024Fвключає відразу три сусідніх блоки):

Зауважте, що \u00C0-\u00FFнасправді є лише частиною латинської добавки 1 . Цей діапазон пропускає недруковані сигнали управління та всі символи, за винятком незграбно розміщеного множення × \u00D7та ділення ÷ \u00F7.

[a-zA-Z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u024F] // exclude ×÷

Якщо вам потрібно більше точок коду, ви можете знайти більше діапазонів у списку символів Вікіпедії Unicode . Наприклад, ви також можете додати латинські розширені-C , D та E , але я їх вийшов із-за того, що зараз цікаві лише історики, а набори D і E навіть не відображаються правильно у моєму браузері.

Оригінальний регулярний вираз, що зупиняється на \u017Fборці на назві "Șenol". За даними аналізатора Unicode FontSpace , першим символом є \u0218ЛАТИНСЬКЕ КАПІТАЛЬНЕ ПІСЛЯ З КОММАЮ ВІДНІШЕ . (Так, зазвичай це написано cedilla-S \u015E, "Şenol". Але я не лечу до Туреччини, щоб поїхати сказати йому: "Ви неправильно написали своє ім'я!")


1
Подивившись латинський блок таблиці unicode , я думаю, ви також повинні включити \ u1e00- \ u1eff, тому я роблю[a-zA-Z\u00c0-\u024f\u1e00-\u1eff]
cprcrack

18

Який із цих трьох підходів найбільше підходить для виконання завдання?

Залежить від завдання :-) Щоб точно відповідати всім латинським символам та їх наголошеним версіям, діапазони Unicode, ймовірно, пропонують найкраще рішення. Вони можуть бути розширені на всі символи, що не містять пробілів, що можна зробити за допомогою \Sкласу символів.

Я змушую поле в інтерфейсі відповідати формату: last_name, first_name(останній [пробіл комами] перший)

Найбільш основна проблема, яку я бачу тут, - це не діакритичність, а пробіли. Є кілька імен, які складаються з декількох слів, наприклад, для назв. Тож вам слід підходити до найбільш загального, тобто дозволити все, крім коми, що відрізняє перше від прізвища:

/[^,]+,\s[^,]+/

Але ваше друге рішення з .класом символів настільки ж чудове, тоді вам може знадобитися подбати про кілька команд.


Гм, можливо, ти маєш рацію. Я, мабуть, надто ускладнив це ... Чи не могли б ви пояснити наданий вами регулярний вираз? Я вже трохи працюю з регексом, але лише основні речі, і насправді я не маю поняття, що робить ваш власне! Ha
Chris Cirefice

Це заперечений клас символів - означає "що-небудь, крім коми".
Бергі

Ах, так це читається більше схоже any_character_not_a_comma, any_character_not_a_comma? Ось що я подумав, коли вперше прочитав це, я розгубився, коли побачив там три коми.
Chris Cirefice

Так саме. Вибачте за плутанину з відсутнім sдля пробілів…
Бергі

1
@ MateoTibaquirá Ви можете спростити [^\s]до\S
Бергі

15

У бібліотеці XRegExp є плагін під назвою Unicode, який допомагає вирішувати подібні завдання.

<script src="xregexp.js"></script>
<script src="addons/unicode/unicode-base.js"></script>
<script>
  var unicodeWord = XRegExp("^\\p{L}+$");

  unicodeWord.test("Русский"); // true
  unicodeWord.test("日本語"); // true
  unicodeWord.test("العربية"); // true
</script>

Це згадується в коментарях до питання, але це легко пропустити. Я помітив це лише після того, як я подав цю відповідь.


Приємно, виявляється, мені насправді не потрібно було повторно виражати unicode, а скоріше за шаблоном anything, anything. Це стане в нагоді майбутнім читачам :)
Кріс Сірефіс


5

Як що до цього?

^([a-zA-Z]|[à-ú]|[À-Ú])+$

Він буде відповідати кожному слову з наголошеними символами чи ні.


2
Але ОП хоче дозволити наголошених символів.
барбасан


3
/^[\pL\pM\p{Zs}.-]+$/u

Пояснення:

  • \pL - відповідає будь-якому виду букви з будь-якої мови
  • \pM - долучає до символу, призначеного для поєднання з іншим символом (наприклад, наголоси, умлаут, коробки, що додаються тощо)
  • \p{Zs} - відповідає символу пробілу, який є невидимим, але займає місце
  • u - Рядки візерунка та теми трактуються як UTF-8

На відміну від інших запропонованих регулярних виразів (таких як [A-Za-zÀ-ÖØ-öø-ÿ]), це буде працювати з усіма специфічними для мови символами, наприклад Šš, узгоджується з цим правилом, але не відповідає іншим на цій сторінці.

На жаль, JavaScript в основному не підтримує ці класи. Однак ви можете використовувати xregexp, наприклад

const XRegExp = require('xregexp');

const isInputRealHumanName = (input: string): boolean => {
  return XRegExp('^[\\pL\\pM-]+ [\\pL\\pM-]+$', 'u').test(input);
};

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.