4

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

(^[\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

有什么想法我哪里出错了吗?

4

3 回答 3

9

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

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

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

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

一个更简单的版本是:

^\w+( \w+)*$
于 2013-03-04T15:09:41.793 回答
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 条有效行。成功!

于 2013-03-04T15:27:41.373 回答
0

\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+)*$

于 2013-03-04T15:34:42.403 回答