请帮助,我的正则表达式技巧失败了。我有以下字符串:
username|email_address|phone_numbers[number]profile[title|addresses[id]]
我希望能够提取方括号之间的任何数据,但不是那些数据是已提取集合的子集的数据。因此,任何嵌套都应该作为父节点提取的字符串的一部分。
在上面的例子中,我提取了两个部分:
"number"
"title|addresses[id]"
请注意[id]没有被提取,因为它是较低级别数据集的一部分。
我一直在尝试使用preg_match来做到这一点,但我认为我可能不得不求助于迭代字符串中的每个字符。
这是一个正则表达式解决方案:
preg_match_all(
'/(?<='[) # Assert that the previous characters is a [
(?: # Match either...
[^[']]* # any number of characters except brackets
| # or
'[ # an opening bracket
(?R) # containing a match of this very regex
'] # followed by a closing bracket
)* # Repeat as needed
(?=']) # Assert the next character is a ]/x',
$subject, $result, PREG_PATTERN_ORDER);
$result = $result[0];
一个可悲的事实是正则表达式不能处理括号匹配,因为正则表达式没有内存。(相当于DFA)
要实现你想要的,你必须自己写一个小解析器(我认为),使用堆栈可以解决这个问题;)
使用栈解决问题的基本思路是…每次你看到[,你会push堆栈,每次你看到],你会弹出堆栈,并撤回你上次看到的[后得到的字符串。
我编写了一个小解析器来实现期望的结果:
代码:
$data = 'username|email_address|phone_numbers[number]profile[title|addresses[id]wut]aaa[another test] aaand another one [which is [more] c[omplexer]t[h[an]] the others]';
print_r(parse($data));
function parse($string, $s1='[', $s2=']'){
$c1 = $c2 = 0;$s = 1;
$l = strlen($string);
$array = array(array(), array());
for($i=0;$i < $l;$i++){
if($string[$i] == $s1){
$c1++;
$array[0][$c1] = $i;
}elseif($string[$i] == $s2){
$c2++;
$array[1][$c2] = $i;
if($c1 == $c2){
$results[] = substr($string, $array[0][$s], $array[1][$c2] - $array[0][$s] + 1);
$s=$c1+1;
}
}
}
return $results;
}
输出:Array
(
[0] => [number]
[1] => [title|addresses[id]wut]
[2] => [another test]
[3] => [which is [more] c[omplexer]t[h[an]] the others]
)
<<p> 在线演示/strong>