代表其位置将正则表达式匹配添加到bidimensional数组

时间:2016-03-31 09:10:22

标签: php arrays regex

我尝试匹配以下模式并创建一个数组,如下所述:

  • 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字符串解析出来,然后在单个爆炸字符串上使用正则表达式。即便想到也不知道如何构建一个阵列,如上所述。

有更好的(更紧凑和优雅)的方式吗?

2 个答案:

答案 0 :(得分:1)

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

$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);

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

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

请参阅regex demo,以下是其解释:

  • c - 文字c
  • (?<start>\d+(?:\[\d+])?) - (组名为&#34;开始&#34;)强制性子模式,\d+匹配1位数字,可选地后跟1次出现:后跟{ {1}} +位+ [
  • ] - 1或0(可选)序列(?:-(?<end>(?&start)?))?后跟&#34; start&#34; group(值放入&#34; end&#34;组)。

答案 1 :(得分:0)

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

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

RegEx Demo

(?P<end>\d+(?:\[\d+\])?|)确保我们还会在end组中捕获空匹配。