我正在尝试编写一个正则表达式来验证数字代码。代码可以是几个有效长度之一,但不是之间的所有长度。我知道我可以做类似的事情
preg_match("/^([0-9]{".$x."}|[0-9]{".$y".})$/", "$string")
但不想为每个有效长度重复子模式。特别是因为我的实际正则表达式已经很复杂了。
preg_match("/^[0-9]{".$x.",".$y."})$/", "$string")
显然对我不起作用,因为它也会匹配
$x
和 $y
之间的任意数字。
使用正则表达式来匹配模式x或y次是更简单的方法吗?
虽然我的完整正则表达式有点复杂,但可以重复 x or y 次的部分非常简单 [0-9],因此像 sln 和 barmar 给出的答案虽然有趣,但将会在这种特殊情况下无法解决问题。
特别是因为我的实际正则表达式已经很复杂了。
那么这是所有正则表达式领域唯一可用的替代方案。
我想既然这是 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
将复杂模式放入变量中,然后在正则表达式中使用它。
$pat = 'complex pattern';
preg_match("/^($pat{" . $x . "}|$pat{" . $y . "})$/", $string);
请注意,顺便说一句,我必须使用串联而不是替换来获取正则表达式中
$x
内的 $y
和 {}
。这是因为 {$var}
是 PHP 字符串中“复杂变量替换”的语法,因此 {}
不会出现在结果字符串中。请参阅有关 双引号字符串的 PHP 文档。
您可以通过利用子模式引用 (
(?1)
) 来避免多次手动编写子模式。将量词逻辑升序排序,然后对两个变量执行减法以计算辅助/可选扩展。
代码:(演示)
$tests = [
'333666',
'333',
'333666999',
];
$x = 6;
$y = 9;
var_export(
preg_grep(
"/^(\d){{$x}}(?:(?1){" . ($y - $x) . "})?$/",
$tests
)
);
输出:
array (
0 => '333666',
2 => '333666999',
)
没有看到你的“复杂模式”,我无法确定我的建议是否是实用/可读的解决方案。