我试图制作一个php正则表达式,解析括号中的文本字符串,同时忽略可能的嵌套括号:
让我们说我想要
Lorem ipsum [1. dolor sit amet, [consectetuer adipiscing] elit.]. Aenean commodo ligula eget dolor.[2. Dolor, [consectetuer adipiscing] elit.] Aenean massa[3. Lorem ipsum] dolor.
返回
[1] => "dolor sit amet, [consectetuer adipiscing] elit."
[2] => "Dolor, [consectetuer adipiscing] elit."
[3] => "Lorem ipsum"
到目前为止我得到了
'/\[([0-9]+)\.\s([^\]]+)\]/gi'
但是当嵌套括号出现时它会中断。 See demo
如何忽略检测中的内括号? Thx提前!
答案 0 :(得分:5)
您可以对以前的组使用递归引用:
(?<no_brackets>[^\[\]]*){0}(?<balanced_brackets>\[\g<no_brackets>\]|\[(?:\g<no_brackets>\g<balanced_brackets>\g<no_brackets>)*\])
我们的想法是将您想要的匹配定义为没有括号的内容,由[]
或其他内容包围,其中包含一系列无括号或平衡括号的第一个规则。
答案 1 :(得分:2)
您可以使用此模式捕获两个不同组中的项目编号和以下文本。如果您确定所有项目编号都是唯一的,则可以使用简单的array_combine
构建问题中描述的关联数组:
$pattern = '~\[ (?:(\d+)\.\s)? ( [^][]*+ (?:(?R) [^][]*)*+ ) ]~x';
if (preg_match_all($pattern, $text, $matches))
$result = array_combine($matches[1], $matches[2]);
模式细节:
~ # pattern delimiter
\[ # literal opening square bracket
(?:(\d+)\.\s)? # optional item number (*)
( # capture group 2
[^][]*+ # all that is not a square bracket (possessive quantifier)
(?: #
(?R) # recursion: (?R) is an alias for the whole pattern
[^][]* # all that is not a square bracket
)*+ # repeat zero or more times (possessive quantifier)
)
] # literal closing square bracket
~x # free spacing mode
(*)请注意,如果您希望能够使用(?R)
的递归,则项目编号部分必须是可选的(例如[consectetuer adipiscing]
不能没有物品编号。)。如果您想避免没有项目编号的方括号,这可能会有问题。在这种情况下,如果将可选组(?:(\d+)\.\s)?
更改为条件语句,则可以构建更健壮的模式:(?(R)|(\d+)\.\s)
条件声明:
(?(R) # IF you are in a recursion
# THEN match this (nothing in our case)
| # ELSE
(\d+)\.\s #
)
这样,物品编号成为强制性的。
答案 2 :(得分:1)
您可以使用递归正则表达式获取方括号括起来的所有子字符串,然后使用preg_replace
内的array_map
删除括号并括起括号:
$str = "Lorem ipsum [1. dolor sit amet, [consectetuer adipiscing] elit.]. Aenean commodo ligula eget dolor.[2. Dolor, [consectetuer adipiscing] elit.] Aenean massa[3. Lorem ipsum] dolor.";
preg_match_all('/\[(?>[^\[\]]|(?R))*]/', $str, $matches);
$res = array_map(function($el) {
return preg_replace('/^\[\d+\.(.*?)\s*\]$/s', '$1', $el);
},
$matches[0]);
print_r($res);
请参阅IDEONE demo
\[(?>[^\[\]]|(?R))*]
正则表达式匹配[
,然后匹配[
和]
或嵌套[...]
结构。在regular-expressions.info查看有关正则表达式递归的更多信息。这是regex demo。
preg_repace
- ^\[\d+\.(.*?)\s*\]$
中的正则表达式将匹配初始[
,其中包含1位或更多位数字以及之后的句点,并将其余内容匹配并捕获到最终的可选空格(\s*
)并关闭]
($
将确保括号在字符串的末尾匹配)。使用$1
,我们可以恢复字符串的其余部分并使用它来填充新数组。请参阅2nd regex demo here。