Конкретное Javascript Regex для акцентированных символов (диакритика)

Я посмотрел на Qaru (замену символов.. eh, как 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]+$/
  • Он соответствует диапазону символов юникода - проверен и работает, хотя я не пробовал ничего сумасшедшего, просто нормальный материал, который я вижу в нашем языковом отделе для имен членов факультета.

Вот мои проблемы:

  • Первое решение слишком ограничено и небрежно и запутанно. Его нужно было бы изменить, если бы я забыл характер или два, и это просто не очень практично.
  • Второе решение лучше, кратким, но, вероятно, оно намного больше, чем на самом деле. Я не мог найти никакой реальной документации о том, что именно соответствует ., просто обобщение "любого символа, кроме символа новой строки" (из таблицы на MDN).
  • Третье решение кажется самым точным, но есть ли какие-либо ошибки? Я не очень хорошо знаком с Unicode, по крайней мере на практике, но смотрю таблицу кодов/продолжение этой таблицы, \u00C0-\u017F кажется довольно прочным, по крайней мере, для ожидаемого ввода.

    • Факультет не будет подавать формы с их именами на своем родном языке (например, на арабском, китайском, японском и т.д.), поэтому мне не нужно беспокоиться о символах с символами, отличными от латиницы

Итак, реальный вопрос (ы): Какой из этих трех подходов наиболее подходит для задачи? Или есть лучшие решения?

Ответ 1

Какой из этих трех подходов наиболее подходит для задачи?

Зависит от задачи:-) Чтобы точно соответствовать всем латинским символам и их акцентированным версиям, диапазоны Unicode, вероятно, обеспечивают лучшее решение. Они могут быть расширены до всех символов без пробелов, которые могут быть выполнены с использованием класса символов \S.

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

Самая основная проблема, которую я вижу здесь, - это не диакритики, а пробелы. Есть несколько имен, которые состоят из нескольких слов, например. для названий. Поэтому вы должны пойти с самым общим, то есть разрешить все, кроме запятой, которая отличает сначала от фамилии:

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

Но ваше второе решение с классом символов . так же хорошо, вам может потребоваться только несколько комматиков.

Ответ 2

Более простой способ принять все акценты заключается в следующем:

[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/ для символов, перечисленных в числовом порядке.

Ответ 3

\u00C0-\u017F латинского диапазона \u00C0-\u017F было недостаточно для моей базы данных имен, поэтому я расширил выражение до

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

Я добавил эти блоки кода (\u00C0-\u024F включает три смежных блока одновременно):

Обратите внимание, что \u00C0-\u00FF на самом деле является лишь частью дополнения Latin-1. Этот диапазон пропускает непечатаемые управляющие сигналы и все символы, кроме неуклюже помещенного умножения × \u00D7 и деления ÷ \u00F7.

  • \u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF может заменить \u00C0-\u00FF для исключения × ÷

Если вам нужно больше кодовых точек, вы можете найти больше диапазонов в Википедии. Список символов Юникода. Например, вы также можете добавить Latin Extended-C, D и E, но я не учел их, потому что сейчас их интересуют только историки, а наборы D и E даже неправильно отображаются в моем браузере.

Оригинальное регулярное выражение, остановившееся на \u017F расторгалось под именем "olenol". Согласно FontSpace Unicode Analyzer, первым символом является \u0218, LATIN CAPITAL LETTER S с запятой ниже. (Да, это обычно пишется с помощью cedilla-S \u015E, "Шенол". Но я не лечу в Турцию, чтобы сказать ему: "Вы пишете свое имя неправильно!")

Ответ 4

Библиотека 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>

Он упомянул в комментариях к вопросу, но его легко пропустить. Я заметил это только после того, как я представил этот ответ.

Ответ 5

Как насчет этого?

/^[a-zA-ZÀ-ÖØ-öø-ÿ]+$/

Ответ 6

Как насчет этого?

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

Он будет соответствовать каждому слову с акцентированными символами или нет.