0

还在学习正则表达式!我的百分比正则表达式(不遵守 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
)

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

4

2 回答 2

6

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

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

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

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

/^(?<int>[1-9][0-9]*|[0])(?<dec>\.[0-9]+)?(?=%?$)/
于 2012-09-21T17:29:37.940 回答
1

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

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

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

因此,以下正则表达式:

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

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

array(5) {
  [0]=>
  string(4) "0.32"
  ["int"]=>
  string(1) "0"
  [1]=>
  string(1) "0"
  ["dec"]=>
  string(3) ".32"
  [2]=>
  string(3) ".32"
}

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

于 2012-09-21T17:32:55.073 回答