php pregmatchall,关于php:使用preg_match_all()获得重复的比赛

我正在尝试使所有子字符串与乘数匹配:

$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实际上比这更复杂。 我知道该怎么做,我只是想知道是否有更短的解决方案。

哇。 在某些情况下,不需要正则表达式时,这是一个很好的解决方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值