php 正则表达式检测括号内的文本忽略嵌套括号
php regex to detect text inside brackets ignoring nested brackets
我正在尝试制作一个 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.
到return
[1] => "dolor sit amet, [consectetuer adipiscing] elit."
[2] => "Dolor, [consectetuer adipiscing] elit."
[3] => "Lorem ipsum"
到目前为止我得到了
'/\[([0-9]+)\.\s([^\]]+)\]/gi'
但是当出现嵌套括号时它会中断。 See demo
如何忽略检测中的内括号?
提前致谢!
您可以使用递归正则表达式获取所有用方括号括起来的子字符串,然后在 array_map
中使用 preg_replace
删除括号和外括号:
$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', '', $el);
},
$matches[0]);
print_r($res);
\[(?>[^\[\]]|(?R))*]
正则表达式匹配 [
,然后匹配 [
和 ]
或嵌套的 [...]
结构。在 regular-expressions.info. Here is the regex demo.
查看更多关于正则表达式递归的信息
preg_repace
- ^\[\d+\.(.*?)\s*\]$
- 中的正则表达式将匹配初始 [
与 1 个或多个数字和一个句点,并匹配并捕获其余部分直到最后可选空格 (\s*
) 和关闭 ]
($
将确保括号在字符串末尾匹配)。使用
我们可以恢复字符串的其余部分并使用它来填充新数组。见 2nd regex demo here.
您可以对之前的组使用递归引用:
(?<no_brackets>[^\[\]]*){0}(?<balanced_brackets>\[\g<no_brackets>\]|\[(?:\g<no_brackets>\g<balanced_brackets>\g<no_brackets>)*\])
我们的想法是将您想要的匹配项定义为不带括号、被 []
包围的内容,或者包含一系列无括号或符合第一条规则的平衡括号的内容。
您可以使用此模式在两个不同的组中捕获项目编号和以下文本。如果您确定所有项目编号都是唯一的,则可以使用简单的 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)
(for例如 [consectetuer adipiscing]
没有商品编号。)。如果您想避免没有项目编号的方括号,这可能会有问题。在这种情况下,如果将可选组 (?:(\d+)\.\s)?
更改为条件语句,则可以构建更强大的模式:(?(R)|(\d+)\.\s)
条件语句:
(?(R) # IF you are in a recursion
# THEN match this (nothing in our case)
| # ELSE
(\d+)\.\s #
)
这样项目编号就变成了强制性的。
我正在尝试制作一个 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.
到return
[1] => "dolor sit amet, [consectetuer adipiscing] elit."
[2] => "Dolor, [consectetuer adipiscing] elit."
[3] => "Lorem ipsum"
到目前为止我得到了
'/\[([0-9]+)\.\s([^\]]+)\]/gi'
但是当出现嵌套括号时它会中断。 See demo
如何忽略检测中的内括号? 提前致谢!
您可以使用递归正则表达式获取所有用方括号括起来的子字符串,然后在 array_map
中使用 preg_replace
删除括号和外括号:
$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', '', $el);
},
$matches[0]);
print_r($res);
\[(?>[^\[\]]|(?R))*]
正则表达式匹配 [
,然后匹配 [
和 ]
或嵌套的 [...]
结构。在 regular-expressions.info. Here is the regex demo.
preg_repace
- ^\[\d+\.(.*?)\s*\]$
- 中的正则表达式将匹配初始 [
与 1 个或多个数字和一个句点,并匹配并捕获其余部分直到最后可选空格 (\s*
) 和关闭 ]
($
将确保括号在字符串末尾匹配)。使用 我们可以恢复字符串的其余部分并使用它来填充新数组。见 2nd regex demo here.
您可以对之前的组使用递归引用:
(?<no_brackets>[^\[\]]*){0}(?<balanced_brackets>\[\g<no_brackets>\]|\[(?:\g<no_brackets>\g<balanced_brackets>\g<no_brackets>)*\])
我们的想法是将您想要的匹配项定义为不带括号、被 []
包围的内容,或者包含一系列无括号或符合第一条规则的平衡括号的内容。
您可以使用此模式在两个不同的组中捕获项目编号和以下文本。如果您确定所有项目编号都是唯一的,则可以使用简单的 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)
(for例如 [consectetuer adipiscing]
没有商品编号。)。如果您想避免没有项目编号的方括号,这可能会有问题。在这种情况下,如果将可选组 (?:(\d+)\.\s)?
更改为条件语句,则可以构建更强大的模式:(?(R)|(\d+)\.\s)
条件语句:
(?(R) # IF you are in a recursion
# THEN match this (nothing in our case)
| # ELSE
(\d+)\.\s #
)
这样项目编号就变成了强制性的。