Regex для имен со специальными символами (Unicode)
Хорошо, я читал о regex весь день и все еще не понимаю его правильно. То, что я пытаюсь сделать, это проверить имя, но функции, которые я могу найти для этого в Интернете, используют только [a-zA-Z]
, оставляя символы, которые мне нужно принять.
Мне в основном нужно регулярное выражение, которое проверяет, что имя не менее двух слов, и что оно не содержит чисел или специальных символов, таких как !"#¤%&/()=...
, однако слова могут содержать символы, такие как æ, é, Â и т.д...
Примером принятого имени будет: "John Elkjærd" или "André Svenson"
Непринятое имя будет:" Hans "," H 4 nn 3 Андерсен "или" Мартин Хенриксен ! "
Если это важно, я использую клиентскую часть функции javascript .match()
и хочу использовать только php preg_replace()
только на отрицательной стороне сервера. (удаление несоответствующих символов).
Любая помощь будет высоко оценена.
Обновление:
Хорошо, спасибо Alix Axel answer У меня есть важная часть вниз, на стороне сервера.
Но поскольку страница из LightWing отвечает, я не могу найти что-либо о поддержке юникода для javascript, поэтому у меня оказалось половина решения для клиента стороне, просто проверяя хотя бы два слова и минимум 5 символов:
if(name.match(/\S+/g).length >= minWords && name.length >= 5) {
//valid
}
Альтернативой было бы указать все символы Юникода, как предложено в переменном ответе, в результате чего я мог бы сделать что-то вроде этого вместе с решением выше, но это хотя и непрактичен.
Ответы
Ответ 1
Попробуйте следующее регулярное выражение:
^(?:[\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, но, вероятно, кто-то здесь будет.
Подтверждает
- John Elkjærd
- Андре Свенсон
- Марко д'Альмейда
- Kristoffer la Cour
недействительными
- Ганс
- H4nn3 Andersen
- Мартин Хенриксен!
Чтобы заменить недопустимые символы, хотя я не уверен, зачем вам это нужно, вам просто нужно немного его изменить:
$name = preg_replace('~[^\p{L}\p{Mn}\p{Pd}\'\x{2019}\s]~u', '$1', $name);
Примеры:
- H4nn3 Andersen → Hnn Andersen
- Мартин Хенриксен! → Мартин Хенриксен
Обратите внимание, что вам всегда нужно использовать модификатор u.
Ответ 2
посетите эту страницу Символы Unicode в регулярном выражении
Ответ 3
вы можете добавить разрешенные специальные символы в регулярное выражение.
Пример:
[a-zA-ZßöäüÖÄÜæé]+
EDIT:
не лучшее решение, но это даст результат, если есть хотя бы слова.
[a-zA-ZßöäüÖÄÜæé]+\s[a-zA-ZßöäüÖÄÜæé]+
Ответ 4
Что касается JavaScript, это более сложно, так как синтаксис JavaScript Regex не поддерживает свойства символа Юникода. Прагматичным решением было бы сопоставление букв следующим образом:
[a-zA-Z\xC0-\uFFFF]
Это позволяет писать буквы на всех языках и исключает числа и все специальные (небуквенные) символы, обычно встречающиеся на клавиатурах. Это несовершенно, поскольку он также позволяет использовать специальные символы unicode, которые не являются буквами, например. смайлики, снеговик и так далее. Однако, поскольку эти символы, как правило, недоступны на клавиатурах, я не думаю, что они будут введены случайно. Поэтому в зависимости от ваших требований это может быть приемлемым решением.
Ответ 5
Здесь оптимизация по фантастическому ответу @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 "Hans" не будет соответствовать.
Наконец, поскольку я нашел этот вопрос, ища аналогичное решение для ruby, вот регулярное выражение, которое можно использовать в Ruby 1.9 +
\A(?:[\p{L}\p{Mn}\p{Pd}\'\U+2019]+(?:\Z|\s+)){2,}\Z
Первичные изменения используют \A и\Z для начала и конца строки (вместо строки) и обозначения символа Ruby Unicode.
Ответ 6
При проверке строки ввода вы можете
- trim(), чтобы удалить ведущие/конечные пробелы
- для сопоставления с [^\w\s] для обнаружения символов без слов\без пробелов
- соответствует \s +, чтобы получить число разделителей слов, равное числу слов + 1.
Однако я не уверен, что сокращение \w содержит акцентированные символы, но оно должно попадать в категорию "слова".
Ответ 7
Это регулярное выражение JS, которое я использую для причудливых имен, составленных с максимальным количеством слов (от 1 до 60 символов), разделенных знаком пространства/одиночной кавычки/минуса
^([a-zA-Z\xC0-\uFFFF]{1,60}[ \-\']{0,1}){1,3}$