正则表达式匹配xa?b?c? 但不是单独的
我正在尝试编写一个匹配xa?b?c的正则表达式? 但不是x。 实际上,'x','a','b'和'c'不是单个字符,它们是适度复杂的子表达式,所以我试图避免像x(abc | ab | ac | bc | A | b | C)。 是否有一种简单的方法在正则表达式中匹配“a,b和c中的至少一个”,或者我运气不好?
这是最短的版本:
(a)?(b)?(c)?(?(1)|(?(2)|(?(3)|(*FAIL))))
如果您需要在一个单独的组中保留比赛,请写下:
((a)?(b)?(c)?)(?(2)|(?(3)|(?(4)|(*FAIL))))
但是,在a
, b
或c
包含捕获组的情况下,这不是非常强大。 所以不要写这个:
(?<A>a)?(?<B>b)?(?<C>c)?(?(<A>)|(?(<B>)|(?(<C>)|(*FAIL))))
如果你需要整个比赛的小组,然后写下这个:
(?<M>(?<A>a)?(?<B>b)?(?<C>c)?(?(<A>)|(?(<B>)|(?(<C>)|(*FAIL)))))
如果像我一样,你更喜欢多字母标识符,并认为这种事情是疯狂的,而不是在/x
模式,写下这个:
(?x)
(?<Whole_Match>
(?<Group_A> a) ?
(?<Group_B> b) ?
(?<Group_C> c) ?
(?(<Group_A>) # Succeed
| (?(<Group_B>) # Succeed
| (?(<Group_C>) # Succeed
| (*FAIL)
)
)
)
)
这里是完整的测试程序来证明这些工作:
#!/usr/bin/perl
use 5.010_000;
my @pats = (
qr/(a)?(b)?(c)?(?(1)|(?(2)|(?(3)|(*FAIL))))/,
qr/((a)?(b)?(c)?)(?(2)|(?(3)|(?(4)|(*FAIL))))/,
qr/(?<A>a)?(?<B>b)?(?<C>c)?(?(<A>)|(?(<B>)|(?(<C>)|(*FAIL))))/,
qr/(?<M>(?<A>a)?(?<B>b)?(?<C>c)?(?(<A>)|(?(<B>)|(?(<C>)|(*FAIL)))))/,
qr{
(?<Whole_Match>
(?<Group_A> a) ?
(?<Group_B> b) ?
(?<Group_C> c) ?
(?(<Group_A>) # Succeed
| (?(<Group_B>) # Succeed
| (?(<Group_C>) # Succeed
| (*FAIL)
)
)
)
)
}x,
);
for my $pat (@pats) {
say "nTESTING $pat";
$_ = "i can match bad crabcatchers from 34 bc and call a cab";
while (/$pat/g) {
say "$`<$&>$'";
}
}
所有五个版本产生这个输出:
i <c>an match bad crabcatchers from 34 bc and call a cab
i c<a>n match bad crabcatchers from 34 bc and call a cab
i can m<a>tch bad crabcatchers from 34 bc and call a cab
i can mat<c>h bad crabcatchers from 34 bc and call a cab
i can match <b>ad crabcatchers from 34 bc and call a cab
i can match b<a>d crabcatchers from 34 bc and call a cab
i can match bad <c>rabcatchers from 34 bc and call a cab
i can match bad cr<abc>atchers from 34 bc and call a cab
i can match bad crabc<a>tchers from 34 bc and call a cab
i can match bad crabcat<c>hers from 34 bc and call a cab
i can match bad crabcatchers from 34 <bc> and call a cab
i can match bad crabcatchers from 34 bc <a>nd call a cab
i can match bad crabcatchers from 34 bc and <c>all a cab
i can match bad crabcatchers from 34 bc and c<a>ll a cab
i can match bad crabcatchers from 34 bc and call <a> cab
i can match bad crabcatchers from 34 bc and call a <c>ab
i can match bad crabcatchers from 34 bc and call a c<ab>
甜,呃?
编辑:对于x
的开头部分,只是把任何x
你想在比赛开始,第一个可选的捕获组之前的a
部分,所以像这样的:
x(a)?(b)?(c)?(?(1)|(?(2)|(?(3)|(*FAIL))))
或者像这样
(?x) # enable non-insane mode
(?<Whole_Match>
x # first match some leader string
# now match a, b, and c, in that order, and each optional
(?<Group_A> a ) ?
(?<Group_B> b ) ?
(?<Group_C> c ) ?
# now make sure we got at least one of a, b, or c
(?(<Group_A>) # SUCCEED!
| (?(<Group_B>) # SUCCEED!
| (?(<Group_C>) # SUCCEED!
| (*FAIL)
)
)
)
)
测试语句是在没有x
部分的情况下构建的,所以它不适用于此,但我想我已经证明了我的意思。 请注意,所有的x
, a
, b
和c
都可以是任意复杂的模式(是,甚至递归),而不仅仅是单个字母,并且它们是否使用它们自己的编号捕获组并不重要。
如果你想用这种方式去做这件事,你可以这样做:
(?x)
(?(DEFINE)
(?<Group_A> a)
(?<Group_B> b)
(?<Group_C> c)
)
x
(?= (?&Group_A)
| (?&Group_B)
| (?&Group_C)
)
(?&Group_A) ?
(?&Group_B) ?
(?&Group_C) ?
以下是在测试程序中添加到@pats
数组中的内容,以显示此方法也适用:
qr{
(?(DEFINE)
(?<Group_A> a)
(?<Group_B> b)
(?<Group_C> c)
)
(?= (?&Group_A)
| (?&Group_B)
| (?&Group_C)
)
(?&Group_A) ?
(?&Group_B) ?
(?&Group_C) ?
}x
你会注意到,即使使用前瞻技术,我仍然设法不要重复a
, b
或c
任何a
。
我赢了吗? ☺
不平凡,如果你没有前瞻。
x(ab?c?|bc?|c)
这个怎么样:
x(?:a())?(?:b())?(?:c())?(1|2|3)
如果a
, b
或c
匹配,则a
, b
和c
之后的空捕获组将始终匹配(空字符串)。
(1|2|3)
部分只有在至少有一个前面的组参加了比赛时才会匹配。 所以如果你只有x
,则正则表达式失败。
正则表达式的每个部分都将被评估一次。
当然,如果x
, a
, b
和c
是更复杂的包含捕获组的子表达式,则必须相应地调整反向引用的数量*。
由于这个正则表达式看起来有点奇怪,下面是详细的版本:
x # Match x
(?:a())? # Try to match a. If this succeeds, 1 will contain an empty string.
(?:b())? # Same with b and 2.
(?:c())? # Same with c and 3.
(1|2|3) # Now try to match the content of one of the backreferences.
# This works if one of the empty parentheses participated in the match.
# If so, the backref contains an empty string which always matches.
# Bingo!
除非你不介意匹配字符串cxba
xb
否则你可能需要用锚( ^
和$
)来包围它。
例如,在Python中:
>>> r=re.compile(r"x(?:a())?(?:b())?(?:c())?(1|2|3)$")
>>> for test in ("x", "xa", "xabc", "xba"):
... m = r.match(test)
... if m:
... print("{} --> {}".format(test, m.group(0)))
... else:
... print("{} --> no match".format(test))
...
x --> no match
xa --> xa
xabc --> xabc
xba --> no match
*或者,如果您的regex flavor知道命名的捕获组,则可以使用这些组
x(?:a(?P<a>))?(?:b(?P<b>))?(?:c(?P<c>))?((?P=a)|(?P=b)|(?P=c))
在Python / PCRE中。 在.NET(以及其他可能的风格)中,拥有多个使用相同名称的捕获组甚至是合法的,这使得另一种简化成为可能:
x(?:a(?<m>))?(?:b(?<m>))?(?:c(?<m>))?k<m>
链接地址: http://www.djcxy.com/p/29867.html