一种更简单的方法来匹配模式 x 或 y 次

问题描述 投票:0回答:3

我正在尝试编写一个正则表达式来验证数字代码。代码可以是几个有效长度之一,但不是之间的所有长度。我知道我可以做类似的事情

preg_match("/^([0-9]{".$x."}|[0-9]{".$y".})$/", "$string")

但不想为每个有效长度重复子模式。特别是因为我的实际正则表达式已经很复杂了。

preg_match("/^[0-9]{".$x.",".$y."})$/", "$string")

显然对我不起作用,因为它也会匹配

$x
$y
之间的任意数字。

使用正则表达式来匹配模式xy次是更简单的方法吗?

编辑:

虽然我的完整正则表达式有点复杂,但可以重复 x or y 次的部分非常简单 [0-9],因此像 slnbarmar 给出的答案虽然有趣,但将会在这种特殊情况下无法解决问题。

php regex preg-match
3个回答
1
投票

特别是因为我的实际正则表达式已经很复杂了。

那么这是所有正则表达式领域唯一可用的替代方案。

我想既然这是 PHP,你总是可以在函数中放置一个单一单位,然后在一系列交替中使用范围量词来调用该函数......

您可以将函数重命名为更具描述性的名称,例如 A、B 或 C ...
最大的优点是您可以注入其他分隔符代码,例如

(?:(?&digit)\s*){4}
或任何你想要的。

 # \b(?:(?&digit){4}|(?&digit){7}|(?&digit){9}|(?&digit){11})\b(?(DEFINE)(?<digit>[0-9]))

 \b                    # add a boundary here
 (?:
      (?&digit){4}          # match 4 times
   |  (?&digit){7}          # or, match 7 times
   |  (?&digit){9}          # or, match 9 times
   |  (?&digit){11}         # or, match 11 times
 )
 \b                    # add a boundary here

 (?(DEFINE)            # Add complex expressions here
      (?<digit> [0-9] )     # (1)
 )

输入:

1234 1234567 123456789

输出:

 **  Grp 0 -  ( pos 0 , len 4 ) 
1234  
 **  Grp 0 -  ( pos 5 , len 7 ) 
1234567  
 **  Grp 0 -  ( pos 13 , len 9 ) 
123456789  

0
投票

将复杂模式放入变量中,然后在正则表达式中使用它。

$pat = 'complex pattern';
preg_match("/^($pat{" . $x . "}|$pat{" . $y . "})$/", $string);

请注意,顺便说一句,我必须使用串联而不是替换来获取正则表达式中

$x
内的
$y
{}
。这是因为
{$var}
是 PHP 字符串中“复杂变量替换”的语法,因此
{}
不会出现在结果字符串中。请参阅有关 双引号字符串的 PHP 文档。


0
投票

您可以通过利用子模式引用 (

(?1)
) 来避免多次手动编写子模式。将量词逻辑升序排序,然后对两个变量执行减法以计算辅助/可选扩展。

代码:(演示

$tests = [
    '333666',
    '333',
    '333666999',
];

$x = 6;
$y = 9;
var_export(
    preg_grep(
        "/^(\d){{$x}}(?:(?1){" . ($y - $x) . "})?$/",
        $tests
    )
);

输出:

array (
  0 => '333666',
  2 => '333666999',
)

没有看到你的“复杂模式”,我无法确定我的建议是否是实用/可读的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.