13

好的,我整天都在阅读关于正则表达式的内容,但仍然没有正确理解它。我想要做的是验证一个名字,但我可以在互联网上找到的功能只使用[a-zA-Z],留下我需要接受的字符。

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

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

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

任何帮助将非常感激。

更新:
好的,感谢Alix Axel 的回答,我已经完成了重要的部分,服务器端的部分。

但正如LightWing 回答的页面所暗示的那样,我找不到任何关于 javascript 的 unicode 支持的信息,所以我最终为客户端提供了一半的解决方案,只需检查至少两个单词和至少 5 个这样的字符:

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

另一种方法是按照shifty's answer中的建议指定所有 unicode 字符,我可能最终会做类似的事情,以及上面的解决方案,但这有点不切实际。

4

7 回答 7

34

试试下面的正则表达式:

^(?:[\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 部分,我无法为您提供帮助,但这里可能有人会。


验证

  • 约翰·埃尔克杰德
  • 安德烈·斯文森
  • 马尔科·达尔梅达
  • 克里斯托弗拉库尔

无效

  • 汉斯
  • H4nn3 安徒生
  • 马丁亨里克森!

要替换无效字符,虽然我不确定你为什么需要这个,你只需要稍微改变一下:

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

例子:

  • H4nn3 安徒生->安徒生
  • 马丁亨里克森!->马丁·亨利克森

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

于 2011-05-11T11:26:00.463 回答
5

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

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

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

于 2013-04-15T08:27:51.837 回答
2

访问此页面正则表达式中的 Unicode 字符

于 2011-05-11T11:17:41.690 回答
2

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

例子:

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

编辑:

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

[a-zA-ZßöäüÖÄÜæé]+\s[a-zA-ZßöäüÖÄÜæé]+
于 2011-05-11T11:25:05.830 回答
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

Essentially, it is saying to find a word as defined by the character class, then either find one or more spaces or an end of a line. The {2,} at the end tells it that a minimum of two words must be found for a match to succeed. This ensures the OP's "Hans" example will not match.


Lastly, since I found this question while looking for a similar solution for , here is the regular expression as can be used in Ruby 1.9+

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

The primary changes are using \A and \Z for beginning and end of string (instead of line) and Ruby's Unicode character notation.

于 2013-06-04T22:29:39.627 回答
0

检查您的输入字符串时,您可以

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

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

于 2011-05-11T11:26:10.213 回答
0

This is the JS regex that I use for fancy names composed with max 3 words (1 to 60 chars), separated by space/single quote/minus sign

^([a-zA-Z\xC0-\uFFFF]{1,60}[ \-\']{0,1}){1,3}$
于 2017-05-16T16:28:56.377 回答