Regexp断言—要么两者都有,要么没有


Regexp assertions - either both or none

我想匹配前面没有x并且后面也没有y的任何数字。我想到了这样的东西:(?<!x)('d+)(?!y)

然而,这并没有真正帮助,因为我还想匹配字符串中的数字,如x123456y

换句话说,我要么两个断言都工作,要么一个都不工作。

例子:

  • 从"x123", "123"匹配
  • 从"456y",匹配"456"
  • 从"789","789"匹配
  • 没有匹配"x123y"

你能帮忙吗?

(?<!'d)(?!(?<=x)'d+(?=y))'d+

基本上,您为想要匹配的内容((?<=x)'d+(?=y))创建一个正则表达式,并将其置于负向前看中。如果成功,就可以继续使用这些数字。但这还不够,因为它仍然会匹配x123y中的23。为数字添加负向后查找确保匹配仅在数字运行的开始处开始。

(?!x'd+y)x?('d+)y?

基本上,您断言只有当不具有x后跟'd+,后跟y时,总体匹配才会成功。然后,您继续匹配数字(为了匹配x123123y,您需要包括可选的xy,但是您从断言中知道,您永远不会同时匹配xy)。

下面是一个简单的Java测试。

如果您不需要它作为一个单独的PCRE表达式,而只是纯代码,您可以像

那样做
#!/usr/bin/perl
foreach $_ (qw(x123 456y x789y)) {
    while ($_ =~ /'d+/g) {
            print "$_'n" if !!(substr($`, -1, 1) ne "x") ^
                            !!(substr($', 0, 1) ne "y");
    }
}

下面是PCRE (single-expr):

foreach $_ (qw(x123 456y x789y)) {
    print "$_'n" if
            /'D*'d+(?!'d)(?!'D)|(?<!x)(?<!'d)'d+'D*/;
}

解释:替代方案1:允许有一个非数字('D),然后一堆数字必须跟在'D +后面,如果是这样,必须没有数字结尾(这样它就不会最终匹配"x789"中的"x78"),也没有非数字。选择2是完全相反的,即在第一个匹配的数字之前必须没有x和数字,并且在'd+之后,可以有任何内容。

一个解决方案:

('b'd+|'d+'b)

Test in perl:

script.pl:

use warnings;
use strict;
while ( <DATA> ) {
    printf qq[$1'n] if m/('b'd+|'d+'b)/;
}   
__DATA__
x123
456y
789
x123y

运行程序:

perl script.pl
结果:

123
456
789
相关文章: