具有特殊字符的名称的正则表达式(Unicode)

时间:2011-05-11 11:08:09

标签: php javascript regex character-properties

好的,我现在已经读了一整天的正则表达式,但仍然不能理解它。我要做的是验证一个名字,但我在互联网上找到的功能只能使用[a-zA-Z],留下我需要接受的字符。

我基本上需要一个正则表达式来检查名称是否至少有两个单词,并且它不包含数字或特殊字符,如!"#¤%&/()=...,但是单词可以包含æ,é,Â等字符上...

一个被接受的名字的例子是:“JohnElkjærd”或“AndréSvenson”
一个不被接受的名字是:“ Hans ”,“H 4 nn 3 Andersen“或”Martin Henriksen

如果重要,我使用javascript .match()函数客户端,并且只想在负面的“服务器端”使用php的preg_replace()。 (删除不匹配的字符)。

非常感谢任何帮助。

更新
好的,感谢Alix Axel's answer我有重要的部分,服务器方面。

但是,正如LightWing's answer的页面所暗示的那样,我无法找到任何关于javascript的unicode支持的内容,所以我最终为客户端找到了半个解决方案,只检查了至少两个单词和最小值5个字符是这样的:

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

另一种方法是指定shifty's answer中建议的所有unicode字符,我可能最终会像上面的解决方案那样做,但这有点不实用。

7 个答案:

答案 0 :(得分:29)

尝试以下正则表达式:

^(?:[\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中seems to work flawlessly @ 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部分无法帮助你,但可能会有人在这里。


<强> void验证

  • JohnElkjærd
  • AndréSvenson
  • Marco d'Almeida
  • Kristoffer la Cour

<强>的失效

  • 汉斯
  • H4nn3 Andersen
  • Martin Henriksen!

要替换无效字符,虽然我不确定您为何需要此字符,但您只需稍微更改一下:

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

示例:

  • H4nn3 Andersen - &gt; Hnn Andersen
  • Martin Henriksen! - &gt; Martin Henriksen

请注意,您始终需要使用 u 修饰符。

答案 1 :(得分:4)

关于JavaScript,它更棘手,因为JavaScript Regex语法不支持unicode字符属性。一个实用的解决方案是匹配这样的字母:

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

这允许使用所有语言的字母,并且不包括数字和键盘上常见的所有特殊(非字母)字符。它是不完美的,因为它还允许unicode特殊符号,这些符号不是字母,例如表情符号,雪人等。但是,由于这些符号通常在键盘上不可用,我认为它们不会偶然输入。因此,根据您的要求,这可能是一个可接受的解决方案。

答案 2 :(得分:2)

答案 3 :(得分:2)

您可以将允许的特殊字符添加到正则表达式。

示例:

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

编辑:

不是最好的解决方案,但如果至少有单词,这会产生结果。

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

答案 4 :(得分:2)

这是@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 1.9 +中使用

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

主要更改是使用\ A和\ Z表示字符串(而不是行)的开头和结尾以及Ruby的Unicode字符表示法。

答案 5 :(得分:0)

检查输入字符串时可以

  • trim()它删除前导/尾随空格
  • 匹配[^ \ w \ s]以检测非word \ non-whitespace字符
  • 与\ s +匹配,以获得等于单词数+ 1的单词分隔符数。

但是我不确定\ w的速记是否包含重音字符,但它应该属于“单词字符”类别。

答案 6 :(得分:0)

这是我使用的JS正则表达式,用于由最多3个单词(1到60个字符)组成的花哨名称,用空格/单引号/减号分隔

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