Regex для имен со специальными символами (Unicode)

Хорошо, я читал о regex весь день и все еще не понимаю его должным образом. То, что я пытаюсь сделать, это проверить имя, но функции, которые я могу найти для этого в Интернете, используют только [a-zA-Z] , оставляя символы, которые мне нужно принять.

Мне в основном нужно регулярное выражение, которое проверяет, что имя не менее двух слов, и что оно не содержит чисел или специальных символов, таких как !"#¤%&/()=... , однако слова могут содержать символы типа æ, é, Â и т. д. …

Примером принятого названия может быть: «John Elkjærd» или «André Svenson»,
Непринятое название будет: « Ганс », «H 4 nn 3 Andersen» или «Martin Henriksen ! »

Если это имеет значение, я использую клиентскую часть функции javascript .match() и хочу использовать php's preg_replace() только «на отрицательной» стороне сервера. (удаление несоответствующих символов).

Любая помощь приветствуется.

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

Но, как говорит страница из ответа LightWing , я не могу найти что-либо о поддержке юникода для javascript, поэтому у меня было половина решения для клиентской стороны, просто проверяя хотя бы два слова и минимум 5 символов:

 if(name.match(/\S+/g).length >= minWords && name.length >= 5) { //valid } 

Альтернативой было бы указать все символы юникода, как было предложено в ответе shifty , и я мог бы сделать что-то вроде этого вместе с решением выше, но это немного непрактично.

Попробуйте следующее регулярное выражение:

 ^(?:[\p{L}\p{Mn}\p{Pd}\'\x{2019}]+\s[\p{L}\p{Mn}\p{Pd}\'\x{2019}]+\s?)+$ 

В PHP это означает:

 if (preg_match('~^(?:[\p{L}\p{Mn}\p{Pd}\'\x{2019}]+\s[\p{L}\p{Mn}\p{Pd}\'\x{2019}]+\s?)+$~u', $name) > 0) { // valid } 

Вы должны прочитать это следующим образом:

 ^ # start of subject (?: # match this: [ # match a: \p{L} # Unicode letter, or \p{Mn} # Unicode accents, or \p{Pd} # Unicode hyphens, or \' # single quote, or \x{2019} # single quote (alternative) ]+ # one or more times \s # any kind of space [ #match a: \p{L} # Unicode letter, or \p{Mn} # Unicode accents, or \p{Pd} # Unicode hyphens, or \' # single quote, or \x{2019} # single quote (alternative) ]+ # one or more times \s? # any kind of space (0 or more times) )+ # one or more times $ # end of subject 

Я честно не знаю, как переносить это на Javascript, я даже не уверен, что Javascript поддерживает свойства Unicode, но в PHP PCRE это работает безупречно @ IDEOne.com :

 $names = array ( 'Alix', 'André Svenson', 'H4nn3 Andersen', 'Hans', 'John Elkjærd', 'Kristoffer la Cour', 'Marco d\'Almeida', 'Martin Henriksen!', ); foreach ($names as $name) { echo sprintf('%s is %s' . "\n", $name, (preg_match('~^(?:[\p{L}\p{Mn}\p{Pd}\'\x{2019}]+\s[\p{L}\p{Mn}\p{Pd}\'\x{2019}]+\s?)+$~u', $name) > 0) ? 'valid' : 'invalid'); } 

Извините, я не могу помочь вам в части Javascript, но, вероятно, кто-то здесь.


Проверяет :

  • Джон Элкьярд
  • Андре Свенсон
  • Marco d'Almeida
  • Kristoffer la Cour

Недопустимо :

  • Hans
  • H4nn3 Андерсен
  • Мартин Хенриксен!

Чтобы заменить недопустимые символы, хотя я не уверен, зачем вам это нужно, вам просто нужно немного изменить его:

 $name = preg_replace('~[^\p{L}\p{Mn}\p{Pd}\'\x{2019}\s]~u', '$1', $name); 

Примеры:

  • H4nn3 Андерсен -> Hnn Andersen
  • Мартин Хенриксен! -> Мартин Хенриксен

Обратите внимание, что вам всегда нужно использовать модификатор u .

просмотреть эту страницу Персонажи Unicode в регулярном выражении

вы можете добавить разрешенные специальные символы в регулярное выражение.

пример:

 [a-zA-ZßöäüÖÄÜæé]+ 

РЕДАКТИРОВАТЬ:

не лучшее решение, но это даст результат, если есть хотя бы слова.

 [a-zA-ZßöäüÖÄÜæé]+\s[a-zA-ZßöäüÖÄÜæé]+ 

Что касается JavaScript, это более сложно, так как синтаксис JavaScript Regex не поддерживает свойства символа Юникода. Прагматичным решением было бы сопоставление букв следующим образом:

 [a-zA-Z\xC0-\uFFFF] 

Это позволяет писать буквы на всех языках и исключает числа и все специальные (небуквенные) символы, обычно встречающиеся на клавиатурах. Это несовершенно, поскольку он также позволяет использовать уникальные символы unicode, которые не являются буквами, например, смайликами, снеговиком и т. Д. Однако, поскольку эти символы, как правило, недоступны на клавиатурах, я не думаю, что они будут введены случайно. Поэтому в зависимости от ваших требований это может быть приемлемым решением.

Вот оптимизация по фантастическому ответу от @Alix выше. Это устраняет необходимость в определении класса символов дважды и позволяет упростить определение любого количества требуемых слов.

 ^(?:[\p{L}\p{Mn}\p{Pd}\'\x{2019}]+(?:$|\s+)){2,}$ 

Его можно разбить следующим образом:

 ^ # start (?: # non-capturing group [ # match a: \p{L} # Unicode letter, or \p{Mn} # Unicode accents, or \p{Pd} # Unicode hyphens, or \' # single quote, or \x{2019} # single quote (alternative) ]+ # one or more times (?: # non-capturing group $ # either end-of-string | # or \s+ # one or more spaces ) # end of group ){2,} # two or more times $ # end-of-string 

По сути, он говорит, чтобы найти слово, определенное классом символов, либо найти одно или несколько пробелов или конец строки. В конце {2,} в конце указывается, что для достижения соответствия должно быть найдено не менее двух слов. Это гарантирует, что пример «Ганса» OP не будет соответствовать.


Наконец, поскольку я нашел этот вопрос, ища аналогичное решение для ruby , вот регулярное выражение, которое можно использовать в Ruby 1.9+

 \A(?:[\p{L}\p{Mn}\p{Pd}\'\U+2019]+(?:\Z|\s+)){2,}\Z 

Первичные изменения используют \ A и \ Z для начала и конца строки (вместо строки) и нотации символов Юникода Ruby.

При проверке входной строки вы можете

  • trim (), чтобы удалить ведущие / конечные пробелы
  • совпадение с [^ \ w \ s] для обнаружения символов, отличных от слова \ non-whitespace
  • сопоставьте с \ s +, чтобы получить количество разделителей слов, равное числу слов + 1.

Однако я не уверен, что в \ w стенография входят символы с акцентом, но они должны попадать в категорию «слова».

Это регулярное выражение JS, которое я использую для причудливых имен, составленных с максимальным количеством слов (от 1 до 60 символов), разделенных знаком «пробел / одинарная кавычка / минус»

 ^([a-zA-Z\xC0-\uFFFF]{1,60}[ \-\']{0,1}){1,3}$