正则表达式断言 - 要么都有要么都没有

3
我想匹配任何一个没有前导x和后继y的数字。 我想出了以下正则表达式: (?<!x)(\d+)(?!y) 然而,这并不能很好地解决问题,因为我也想匹配像x123456y这样的字符串中的数字。
换句话说,我要么两个断言都生效,要么一个也不生效。
示例:
  • 从 "x123" 中匹配到 "123"
  • 从 "456y" 中匹配到 "456"
  • 从 "789" 中匹配到 "789"
  • 从 "x123y" 中什么也不匹配
请问能帮忙吗?

这些数字是不是属于一个更大的字符串?还有使用的是哪种编程语言? - FailedDev
@FailedDev 是的,它们是。这种语言是PHP。 - JirkaVebr
4个回答

2
(?<!\d)(?!(?<=x)\d+(?=y))\d+

基本上,你需要创建一个正则表达式来匹配你不想匹配的内容 - (?<=x)\d+(?=y) - 并将其放入否定先行断言中。如果成功,你就可以继续消耗数字了。但这还不够,因为它仍然会匹配x123y中的23。添加一个数字的否定后行断言可以确保匹配只从数字的开头开始。

0
(?!x\d+y)x?(\d+)y?

基本上,你断言只有在你没有一个由x跟随的\d+,然后是一个y时,整体匹配才会成功。然后,你继续匹配数字(你需要包括可选的xy以匹配x123123y,但是你从断言中知道,你永远不会同时匹配xy)。

这里是一个简单的Java test


0

如果您不需要将其作为单个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(单表达式):

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

解释: 备选项1:允许有一个非数字字符(\D),然后必须跟着一堆数字\d+,如果是这样,就不能有数字尾随(以防止它只匹配“x789”中的“x78”),也不能有非数字字符。 备选项2是完全相反的,即第一个匹配的数字之前不能有x和数字,在\d+之后可以是任何内容。


0
一个解决方案:
(\b\d+|\d+\b)

使用 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接