【问题标题】:Regex for multiple words split by spaces用空格分割的多个单词的正则表达式
【发布时间】:2013-03-04 15:02:47
【问题描述】:

我正要把头撞在桌子上,这让我的同事们很开心。我目前有以下正则表达式

(^[\w](( \w+)|(\w*))*[\w]$)|(^\w$)

我想要它做的是匹配任何只包含字母数字字符、没有前导或尾随空格并且单词之间不超过一个空格的字符串。

在这种情况下,单词被定义为一个或多个字母数字字符。

这符合我想要的大部分内容,但是通过测试它还认为第二个单词以后的长度必须是 2 个字符或更多。

测试:

ABC - Pass
Type 1 - Fail
Type A - Fail
Hello A - Fail
Hello Wo - Pass
H A B - Fail
H AB - Pass
AB H - Fail

任何想法我哪里出错了?

【问题讨论】:

  • @Bergi:这应该是一个答案。没有比这更简单和更好的了(好吧,你可以使用非捕获组)。
  • 我不确定 OPs 复杂版本中的所有这些捕获组是否都是有意的......
  • @Bergi tbh 此时我只是在尝试任何东西,而正则表达式只是变得越来越大哈哈。你的回答正是我想要的。谢谢

标签: regex


【解决方案1】:

你的正则表达式很接近。你的双字符问题的原因在这里:

(^[\w](( \w+)|(\w*))*[\w]$)|(^\w$)
       right here ---^

在匹配组( \w+) 后,即一个空格后跟一个或多个\w,由于空格,第一个单词之后的每个单词都必须匹配,然后你有另一个强制性\w - 这需要字符串中的最后一个单词有两个或多个字符。把那个拿出来应该没问题:

(^[\w](( \w+)|(\w*))*$)|(^\w$)

更简单的版本是:

^\w+( \w+)*$

【讨论】:

  • 不,这些事情可能很棘手和混乱。用新的眼光审视一遍又一遍的代码总是有帮助的。
  • 具有嵌套量词和重叠交替范围的正则表达式看起来像是灾难性回溯的高风险候选者。 @JonTaylor 的要求可以更简洁准确地指定。请参阅 Bergi 的评论。
  • @TimPietzcker 对,因此我给出了更简单的版本。
  • 我相信[a-z] 只匹配小写字母而不管字符编码。
  • UTF 对拉丁字母的编码与 ASCII 完全相同。如果语言环境有问题,您可以使用 POSIX 标准类 [:lower:](假设您的语言符合 POSIX)。我不知道这什么时候真的会成为一个问题,但如果需要,那就去吧。
【解决方案2】:

将 PCRE 与 POSIX 类一起使用

首先,我们需要清理您的语料库,因为它们包含破折号。接下来,我们添加一两行肯定会失败的代码,这样我们就有了一条悲伤的测试路径。这会产生以下语料库:

# /tmp/corpus
ABC
Type 1
Type A
Hello A
Hello Wo
H A B
H AB
AB H
ab $ cd

接下来,我们将锚定的 Perl 兼容正则表达式与仅包含字母数字值的 POSIX 类一起使用。我们使用负前瞻来防止尾随空格,但允许单词之间有一个空格。

$ pcregrep '^([[:alnum:]]+(?!= $) ?)+$' /tmp/corpus
ABC
Type 1
Type A
Hello A
Hello Wo
H A B
H AB
AB H

正如预期的那样,这会产生您所期望的 8 条有效行。成功!

【讨论】:

  • 这不会拒绝以空格结尾的字符串。
  • @TimPietzcker 感谢您指出这一点;我用负面的前瞻来修复它。当然,并不是所有的 grep 或正则表达式引擎都支持该功能,但我认为如果您的工具支持,这个结果会更容易阅读。
  • (?!=$) 不会像您认为的那样做。相反,您需要在字符串结尾处查看(?<! )。除非您使用(?=\w$),否则前瞻将不起作用。
【解决方案3】:

\w 将匹配 _ 以及字母数字。因此,如果您不想匹配下划线,则必须改用 [a-zA-Z\d]。

以下表达式应满足您的需求:

^[a-zA-Z\d]+(?: [A-Za-z\d]{2,})*$

如果不支持 {min,max} 重复,您也可以使用以下选项。

^[A-Za-z\d]+(?: [A-Za-z\d][A-Za-z\d]+)*$

我们需要 {min,max} 或双字符组,因为您要求从第二个单词开始最少 2 个字符。

如果允许使用下划线,那么下面的表达式会更好:

^\w+(?: \w{2,})*$

或者没有{min,max}:

^\w+(?: \w\w+)*$

【讨论】:

    猜你喜欢
    • 2015-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-25
    • 1970-01-01
    • 2013-09-16
    • 2016-11-29
    相关资源
    最近更新 更多