Хорошо, я читал о 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, но, вероятно, кто-то здесь.
Проверяет :
Недопустимо :
Чтобы заменить недопустимые символы, хотя я не уверен, зачем вам это нужно, вам просто нужно немного изменить его:
$name = preg_replace('~[^\p{L}\p{Mn}\p{Pd}\'\x{2019}\s]~u', '$1', $name);
Примеры:
Обратите внимание, что вам всегда нужно использовать модификатор 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.
При проверке входной строки вы можете
Однако я не уверен, что в \ w стенография входят символы с акцентом, но они должны попадать в категорию «слова».
Это регулярное выражение JS, которое я использую для причудливых имен, составленных с максимальным количеством слов (от 1 до 60 символов), разделенных знаком «пробел / одинарная кавычка / минус»
^([a-zA-Z\xC0-\uFFFF]{1,60}[ \-\']{0,1}){1,3}$