正则表达式在PHP中命名为捕获组
我有以下正则表达式来捕获一个数字列表(最终会比这更复杂): 如何在$matches数组中捕获列表中的单个数字?我似乎无法做到这一点,尽管在数字(\d+)周围放置了一个捕获组 编辑 为了更清楚,我希望最终使用递归,因此explode并不理想:正则表达式在PHP中命名为捕获组,php,regex,Php,Regex,我有以下正则表达式来捕获一个数字列表(最终会比这更复杂): 如何在$matches数组中捕获列表中的单个数字?我似乎无法做到这一点,尽管在数字(\d+)周围放置了一个捕获组 编辑 为了更清楚,我希望最终使用递归,因此explode并不理想: $match = <<<REGEX /(?x) (?(DEFINE) (?<number> (\d+) ) (?<member> (?&number)|(?&
$match =
<<<REGEX
/(?x)
(?(DEFINE)
(?<number> (\d+) )
(?<member> (?&number)|(?&list) )
(?<list> \( ((?&number)|(?&member))(,(?&member))* \) )
)
^(?&list)/
REGEX;
$match=
若要获取逗号分隔的数字数组,请分解:
$numbers = explode(',', $matches[0]); //first parameter is your delimiter what the string will be split up by. And the second parameter is the initial string
print_r($numbers);
输出:
Array(
[0] => 10,
[1] => 9,
[2] => 8,
etc对于这个简单的列表,这就足够了(如果必须使用正则表达式):
(?(DEFINE)…)
部分的目的只是定义命名子模式,您可以稍后在DEFINE部分本身或主模式中使用。因为这些子模式没有在主模式中定义,所以它们不会捕获任何内容,而引用(?&number)
只是子模式\d+
的一种别名,也不会捕获任何内容
字符串示例:1abcde2
如果我使用此模式:/^(?\d)…(?&num)$/
组num中只捕获1
,(?&num)
不捕获任何内容,它只是\d
/^(?\d)…\d$/
的别名,产生完全相同的结果
还有一点需要澄清。使用PCRE(PHP正则表达式引擎),捕获组(无论是否命名)只能存储一个值,即使您重复它
你的方法的主要问题是你试图同时做两件事:
您想检查字符串的格式
您想提取未知数量的项目
这样做只有在特定情况下才可能,但在一般情况下是不可能的
例如,使用平面列表,如:$list='10,9,8,7,6,5,4,3,2,1'代码>在没有嵌套元素的情况下,可以使用类似于preg\u match\u all
的函数以这种方式多次重用同一模式:
if (preg_match_all('~\G(\d+)(,|$)~', $list, $matches) && !end($matches[2])) {
// \G ensures that results are contiguous
// you have all the items in $matches[1]
// if the last item of $matches[2] is empty, this means
// that the end of the string is reached and the string
// format is correct
echo '<°)))))))>';
}
一次传球是不行的。您需要一个模式来检查整个字符串格式,另一个模式来提取元素(以及使用它的递归函数)
谢谢你,至少我知道这是不可能的。环顾四周,似乎只有.NET正则表达式捕获了所有重复组。不过,递归匹配还是相当强大的@GuillermoPhillips:新的python正则表达式模块也可以这样做。实际上,您可以通过添加另一组括号来捕获第二个数字,如/^(?\d)…((?&num))$/,但是,第二个组将被捕获为\2,即未命名。@RudigerW://显然,但这只是一个例子来说明反向引用不是捕获这一事实。
Array(
[0] => 10,
[1] => 9,
[2] => 8,
$string = '10,9,8,7,6,5,4,3,2,1';
$pattern = '/([\d]+),?/';
preg_match_all($pattern, $string, $matches);
print_r($matches[1]);
if (preg_match_all('~\G(\d+)(,|$)~', $list, $matches) && !end($matches[2])) {
// \G ensures that results are contiguous
// you have all the items in $matches[1]
// if the last item of $matches[2] is empty, this means
// that the end of the string is reached and the string
// format is correct
echo '<°)))))))>';
}
[ 10, 9, [ 8, [ 7, 6 ], 5 ], 4 , [ 3, 2 ], 1 ]
eval('$result=[' . strtr($list, '()', '[]') . '];');