将正则表达式匹配项代表其位置添加到二维数组中


Add regex matches to bidimensional array on behalf of their position

我正在尝试匹配以下模式并创建如下所述的数组:

  • letter 'c' followed by digit
  • letter 'c' followed by digit dash digit
  • digit may be followed by an other digit enclosed in square parentheses []

模式用逗号分隔。

示例:

c2,c3-5,c6[2],c8[4]-10,c14-21[5]

这些数字是对法律条款段落的引用,其中有破折号意味着这是一系列段落。

例如:

c3-5 = paragraphs from 3 to 5

使用以下正则表达式,我可以匹配和分离数字:

('d+('['d+'])?-'d+('['d+'])?)|('d+('['d+'])?)

https://regex101.com/r/iQ2pQ3/1

但为了有效地使用这些数字,我试图构建一个具有以下结构的阵列,但没有成功:

Array 
(
    [0] => Array
    (
        [start] => 2
        [end]=> 
    )
    [1] => Array
    (
        [start] => 3
        [end] => 5
    )
    [2] => Array
    (
        [start] => 6[2]
        [end] =>
    )
    [3] => Array
    (
        [start] => 8[4]
        [end] => 10
    )
    [4] => Array
    (
        [start] => 14
        [end] => 21[5]
    )
)

您可以看到,单个匹配项是用关键字[start]添加到数组中的,当有短划线(范围)时,第一个数字用关键字[start]添加,第二个数字用密钥[end]添加。

我认为唯一的方法是通过逗号首先explode字符串,然后在单个分解的字符串上使用正则表达式。即使是思想也不知道如何构建如上所述的数组。

有更好(更紧凑、更优雅)的方法吗?

使用以下基于正则表达式的解决方案(请参阅演示):

$re = '~c(?<start>'d+(?:'['d+])?)(?:-(?<end>(?&start)?))?~'; 
$str = "c2,c3-5,c6[2],c8[4]-10,c14-21[5]"; 
preg_match_all($re, $str, $matches);
$res = array_map(function($ms, $me) { 
    return array("start" => $ms, "end" => $me);
}, $matches["start"], $matches["end"]);
print_r($res);

regex与anubhava的类似,但我在命名子例程调用的帮助下缩短了它(它实际上递归、重显start子模式):

c(?<start>'d+(?:'['d+])?)(?:-(?<end>(?&start)?))?

请参阅regex演示,下面是它的解释:

  • c-文字c
  • (?<start>'d+(?:'['d+])?)-(名为"start"的组)一个强制性子模式,'d+匹配1个以上数字,可选后接1个:,后接[+数字+]
  • (?:-(?<end>(?&start)?))?--的1或0(可选)序列,后跟"开始"组(该值放入"结束"组)

您可以将正则表达式修改为这样,以捕获空匹配:

c(?P<start>'d+(?:'['d+'])?)-?(?P<end>'d+(?:'['d+'])?|)(?=,|$)

RegEx演示

(?P<end>'d+(?:'['d+'])?|)确保我们也捕获end组中的空匹配。