我正在尝试使所有子字符串与乘数匹配:
$list = '1,2,3,4';
preg_match_all('|\d+(,\d+)*|', $list, $matches);
print_r($matches);
此示例按预期返回[1]中的最后一个匹配项:
Array
(
[0] => Array
(
[0] => 1,2,3,4
)
[1] => Array
(
[0] => ,4
)
)
但是,我想用(,\d+)匹配所有字符串,以得到类似的东西:
Array
(
[0] => ,2
[1] => ,3
[2] => ,4
)
有没有办法使用单个功能(例如preg_match_all())来执行此操作?
语言不同,但答案与stackoverflow.com/questions/6571106相同:您不能,但可以轻松地用,分开。
@Kobi:谢谢您的链接。 根据他们的说法,有些语言有解决方案,对PHP有希望吗?或者这是确定的答案?
[0] => ,2在PHP中是不可能的。 ,2是字符串还是数字?
不。据我所知,如果您坚持使用整个正则表达式解决方案,则PHP不支持对同一组的捕获。
正如已经建议的:explode(...)是更好的选择。 您可以这样做:preg_match_all(|(\d+)|, $list, $matches);,但是不能保证输入的字符串是一个用数字分隔的逗号分隔的字符串!
谢谢科比。 如果您有答案,我会接受的:-)
根据Kobi(请参阅上面的评论):
PHP has no support for captures of the same group
因此,这个问题没有解决方案。
使用lookbehind是完成这项工作的一种方式:
$list = '1,2,3,4';
preg_match_all('|(?<=\d),\d+|', $list, $matches);
print_r($matches);
所有,\d+都在组0中。
输出:
Array
(
[0] => Array
(
[0] => ,2
[1] => ,3
[2] => ,4
)
)
确实,PHP(或更确切地说说PCRE)不存储重复捕获组的值以供以后访问(请参阅PCRE文档):
If a capturing subpattern is matched repeatedly, it is the last portion of the string that it matched that is returned.
但是在大多数情况下,已知令牌\G可以完成任务。 \G 1)匹配输入字符串的开头(如未设置m修饰符时为\A或^)或2)从上一个匹配结束处开始匹配。这样说,您必须像下面这样使用它:
preg_match_all('/^\d+|\G(?!^)(,?\d+)\K/', $list, $matches);
在这里观看现场演示
或捕获组无关紧要:
preg_match_all('/\G,?\d+/', $list, $matches);
$matches通过它来保存此内容(请参见现场演示):
Array
(
[0] => Array
(
[0] => 1
[1] => ,2
[2] => ,3
[3] => ,4
)
)
注意:使用\G而不是其他答案(例如explode()或后向解决方案或仅preg_match_all('/,?\d+/', ...))的好处是,您可以同时验证输入字符串是否仅采用所需格式^\d+(,\d+)*$导出比赛的时间:
preg_match_all('/(?:^(?=\d+(?:,\d+)*$)|\G(?!^),)\d+/', $list, $matches);
从http://www.php.net/manual/en/regexp.reference.repetition.php:
When a capturing subpattern is repeated, the value captured is the substring that matched the final iteration.
同样类似的线程:
如何使用preg_match_all()获取子组匹配的所有捕获?
仅当模式中未使用要拆分的字符来匹配自身时,拆分才是一种选择。
我遇到一种情况,必须将格式错误的逗号分隔行解析为许多已知选项中的任何一个。
即选项" 1,2"," 2"," 2,3"
主题" 1,2,3"。
在','上分割将得到'1','2'和'3';仅其中一个('2')是有效匹配项,这是因为分隔符也是选项的一部分。
天真的正则表达式将类似于'?^(1,2 | 2 | 2,3)(?:,(1,2 | 2 | 2,3))* $?i',但这会碰到同组捕获的问题。
我的"解决方案"是扩展正则表达式以匹配可能的最大匹配数:
'?^(1,2 | 2 | 2,3)(?:,(1,2 | 2 | 2,3))?(?:,(1,2 | 2 | 2,3))?$?一世'
(如果有更多选项可用,则只需重复'(?:,(1,2 | 2 | 2,3,))?'位。
确实会导致"未使用"匹配的字符串结果为空。
这不是最干净的解决方案,但在必须处理格式错误的输入数据时可以使用。
为什么不只是:
$ar = explode(',', $list);
print_r($ar);
上面的示例只是一个简化,而regexp实际上比这更复杂。 我知道该怎么做,我只是想知道是否有更短的解决方案。
哇。 在某些情况下,不需要正则表达式时,这是一个很好的解决方案。