[英]Overlapping matches with preg_match_all and pattern ending with repeated character
[英]Get repeated matches with 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
)
有沒有辦法用一個 function 例如preg_match_all()
做到這一點?
確實,PHP(或者更好的說法是 PCRE)不會存儲重復捕獲組的值以供以后訪問(請參閱PCRE 文檔):
如果重復匹配捕獲子模式,則返回匹配的字符串的最后一部分。
但在大多數情況下,已知令牌\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()
或lookbehind 解決方案或只是preg_match_all('/,?\d+/', ...)
)的好處是您能夠驗證輸入字符串是僅在導出匹配項時同時以所需的格式^\d+(,\d+)*$
:
preg_match_all('/(?:^(?=\d+(?:,\d+)*$)|\G(?!^),)\d+/', $list, $matches);
使用lookbehind是一種完成工作的方法:
$list = '1,2,3,4';
preg_match_all('|(?<=\d),\d+|', $list, $matches);
print_r($matches);
所有,\d+
都在第 0 組中。
output:
Array
(
[0] => Array
(
[0] => ,2
[1] => ,3
[2] => ,4
)
)
只有當模式中沒有使用要拆分的字符來匹配自身時,拆分才是一種選擇。 我有一種情況,必須將格式錯誤的逗號分隔行解析為許多已知選項中的任何一個。
即選項'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))?$~i' (如果有更多選項可用,只需重復 '(?:,(1,2|2|2,3))?'位。這確實會導致“未使用”匹配的空字符串結果。
這不是最干凈的解決方案,但在您必須處理格式錯誤的輸入數據時有效。
從http://www.php.net/manual/en/regexp.reference.repetition.php :
當重復捕獲子模式時,捕獲的值是與最終迭代匹配的 substring。
還有類似的線程:
為什么不只是:
$ar = explode(',', $list);
print_r($ar);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.