【问题标题】:I think that this regular expression should not fail, what I'm missing?我认为这个正则表达式不应该失败,我错过了什么?
【发布时间】:2012-09-14 13:58:17
【问题描述】:
^(?![_\.\'\-])(?:[\p{L} ]+)$

如果我理解正确的话,有:

  • (?![_\.\'\-]) 否定前瞻,即字符串不能以下划线、点、撇号或减号(任意数量)开头。
  • (?:[\p{L} ]+) 允许在 Ll、Lm、Lo、Lt 和 Lu 以及空格中至少有一个字符。

第一个问题是:像“1Bob”这样的东西不应该失败(因为前瞻)。那么why it fails

第二个问题在哪里可以找到 Ll、Lm、Lo、Lt 和 Lu 中的字符列表或解释?

【问题讨论】:

    标签: php regex unicode pcre


    【解决方案1】:

    数字 "1"\p{L} 不匹配(这仅匹配字母!)。如果你想匹配任何(数字)数字,也可以使用 \p{N} 类:

    $text = "1Bob";
    
    if (preg_match("/^(?![_\.\'\-])(?:[\p{N}\p{L} ]+)$/u", $text)) {
      echo "Matched!\n";
    } else {
      echo "No match...\n";
    }
    

    将打印:

    Matched!
    

    此外,Ruby 的正则表达式引擎与 PHP 的正则表达式引擎之间也存在细微差别。由于您的目标语言似乎是 PHP,因此我建议使用 PHP 进行测试,而不是使用 Rubular (Ruby)。

    请注意,在字符类中,“普通”正则表达式元字符没有任何特殊能力并且不需要转义:preg_match("/^(?![_.'-])(?:[\p{N}\p{L} ]+)$/u", $text)

    可以在此处找到许多 Unicode 字符属性/类的概述:http://www.regular-expressions.info/unicode.html

    【讨论】:

    • 那么,“1Bob”失败是因为第二组,而不是因为前瞻?
    • @Gremo,正确,只需执行以下操作即可验证:if (preg_match("/^(?![_\.\'\-])/", $text)) { ... }
    • 另外,您可以在前瞻字符类中删除所有这些反斜杠。我认为,您可能还需要使用 /u 修饰符,以便 Unicode prüperties 正常工作。
    • @BartKiers:它是否也适用于非 ASCII 字母?抱歉打错了...s/prüperties/properties :)
    • @TimPietzcker,嘿嘿,我搞砸了一些正则表达式问答:我以为这个里面有一个非 ascii... :)
    【解决方案2】:
    (?![_\.\'\-])
    

    相同
    (?![_.'-])
    

    括号字符类中的大多数元字符不需要转义。如果破折号是可理解范围的一部分,则需要转义。由于破折号位于括号字符类的末尾,因此也不需要转义。

    【讨论】:

    • 虽然这是真的,但这不是对 OP 问题的答案:此类评论更适合作为问题下方的评论,而不是作为答案发布。
    • Bart Kiers - 谢谢,我是新来的。格式对 cme​​ts 不是不好(不允许换行)?
    • @protist 很高兴知道。是否有要转义的字符的快速参考?
    • Gremo - perldoc perlrecharclass 有一个“括号字符类”部分。你也可以在这里看到相同的信息perldoc.perl.org/perlrecharclass.html
    • @protist,是的,cmets 不太适合长文本块。但是在 SO 上,“答案”必须(或应该)是对问题的真实答案。它不像一个经典的论坛,将 cmets 添加到帖子中,这里它必须(或应该)是问题和答案。您不必删除您的此评论/答案,但只是为了让您知道 SO 应该如何工作。欢迎! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-18
    • 2010-12-17
    • 1970-01-01
    • 1970-01-01
    • 2010-12-10
    相关资源
    最近更新 更多