不捕获我的PHP正则表达式中的百分号?

时间:2012-09-21 17:25:59

标签: php regex preg-match percentage

还在学习正规表达!我的正则表达式百分比(不遵守100限制):

^(?<int>[1-9][0-9]*|[0])(?<dec>\.[0-9]+)?\%?$

应该允许:

  • [1-9]以不同于0的数字开头。不允许使用“004.34”等百分比。
  • [0-9]* ...后跟0到9之间的任何数字
  • |[0]或以单个0
  • 开头

...将此组捕获为“int”组。然后:

  • (?<dec>\.[0-9]+)?一个可选组,只有在0到9之间至少有一个数字后才允许一个点。我不想让人输入,即“33”。

假设我是对的,请测试:

preg_match('/^(?<int>[1-9][0-9]*|[0])(?<dec>\.[0-9]+)?\%?$/i', '0.32%', $result);

给我这个结果,这实际上是正确的,但是:

Array
(
    [0] => 0.32%
    [int] => 0
    [1] => 0
    [dec] => .32
    [2] => .32
)

如何避免捕获百分比“%”符号(在$result[0]中)?

2 个答案:

答案 0 :(得分:6)

真的很简单。只需将你的正则表达式改为:

/^(?<int>[1-9][0-9]*|[0])(?<dec>\.[0-9]+)?/

(从匹配中删除\%?$。)

如果你想确保%符号存在,但是不想捕获它(在这种情况下似乎无关紧要,但也许)你可以添加一个前瞻断言。 (?=...)断言确保模式存在,但它不会改变匹配的内容。

/^(?<int>[1-9][0-9]*|[0])(?<dec>\.[0-9]+)?(?=%?$)/

答案 1 :(得分:1)

$result数组的第一个元素将始终包含完整模式匹配(您不能告诉PHP不这样做,请参阅here),因此我们必须解决正则表达式本身的问题。在正则表达式中,您指定% 完整模式匹配 ,因为您明确告诉它可能出现在之前(以及内部)模式字符串($符号)的结尾,您可以在此处\%?$

解决方案是在前瞻中指定%(因此它不会进入模式字符串),并且由于%是可选的,我们会在前瞻中查找{ {1}}或字符串结尾,因此%永远不会进入完整模式匹配。

所以我添加了%,告诉正则表达式提前查看(?=\%|$)符号或字符串的结尾。

所以,以下正则表达式:

%

对于'0.32%'和'0.32'将输出:

preg_match('/^(?<int>[1-9][0-9]*|[0])(?<dec>\.[0-9]+)?(?=\%|$)/i', '0.32%', $result);

更新:我做了一些测试后更新了我的完整答案,所以请阅读上面的内容