正则表达式 - 匹配第二个结束标记而不是第一个
Regex - Matching with the second closing tag instead of the first one
我正在尝试找到正确的模式来匹配 [CODE] 块中的一个或多个 [U]。
以下是包含我要匹配的标签的示例结构。模式应该找到第二个 [CODE] 块。
[CODE]
...there is no U tag here...
[/CODE]
[U]out of the code tags[/U]
[CODE]
...something else...
[U]inside the code tags[/U]
...something else...
[/CODE]
我正在使用以下模式:
/\[CODE\](.*)\[U\](.*)\[\/U\](.*)\[\/CODE\]/gisU
然而它与中间两个 CODE 块中的 U 标记匹配,认为第一个 [CODE] 和最后一个 [/CODE] 是它正在寻找的。
我怎样才能让它工作,所以它会看到第一个结束标记 [/CODE],并且不会与外部 [U] 匹配,而是与第二个 [CODE] 块内的匹配?
注意:我尝试使用 ([^[/CODE]]*) 与模式中 [U] 之前的结束标记 [/CODE] 不匹配,但无法使其工作。显然不太擅长这个。
如有任何帮助,我们将不胜感激。谢谢!
这是一个解决方案preg_match_all
:
$input = "[CODE]\n...there is no U tag here...\n[/CODE]\n\n[U]out of the code tags[/U]\n\n[CODE]\n...something else...\n[U]inside the code tags[/U]\n\n...something else...\n[/CODE]";
preg_match_all("/\[CODE\]((?!\[\/?CODE\]).)*\[U\].*?\[\/CODE\]/s", $input, $matches);
print_r($matches[0]);
Array
(
[0] => [CODE]
...something else...
[U]inside the code tags[/U]
...something else...
[/CODE]
)
关于 PHP 代码本身不需要过多提及,除了我们使用 s
标志和 preg_match_all
,以确保我们 运行 中的正则表达式全点模式。这是必需的,因为您的内容跨越多行。
这里是对所用正则表达式的解释:
\[CODE\] match an initial [CODE] tag
((?!\[\/?CODE\]).)* consume anything so long it is not an opening OR closing [/CODE] tag
\[U\] consume an opening [U] tag
.*? then consume anything up until the first
\[\/CODE\] closing [/CODE] tag
上面的大部分正则表达式都很简单,除了以下部分:
((?!\[\/?CODE\]).)*
这使用了一种叫做 tempered 点的东西,它表示一次向前迈出一步,在每一步检查我们没有遇到空位 [CODE]
或关闭 [/CODE]
标签。这确保我们匹配 [CODE]...[/CODE]
标签集中的 [U]
标签。
请注意,我的回答假设您的输入格式正确,即除了您向我们展示的内容之外没有标签嵌套,并且每个开始标签都有一个适当的结束标签。如果您需要在此基础上进行验证,那么您将不得不做更多的工作。
我正在尝试找到正确的模式来匹配 [CODE] 块中的一个或多个 [U]。
以下是包含我要匹配的标签的示例结构。模式应该找到第二个 [CODE] 块。
[CODE]
...there is no U tag here...
[/CODE]
[U]out of the code tags[/U]
[CODE]
...something else...
[U]inside the code tags[/U]
...something else...
[/CODE]
我正在使用以下模式:
/\[CODE\](.*)\[U\](.*)\[\/U\](.*)\[\/CODE\]/gisU
然而它与中间两个 CODE 块中的 U 标记匹配,认为第一个 [CODE] 和最后一个 [/CODE] 是它正在寻找的。
我怎样才能让它工作,所以它会看到第一个结束标记 [/CODE],并且不会与外部 [U] 匹配,而是与第二个 [CODE] 块内的匹配?
注意:我尝试使用 ([^[/CODE]]*) 与模式中 [U] 之前的结束标记 [/CODE] 不匹配,但无法使其工作。显然不太擅长这个。
如有任何帮助,我们将不胜感激。谢谢!
这是一个解决方案preg_match_all
:
$input = "[CODE]\n...there is no U tag here...\n[/CODE]\n\n[U]out of the code tags[/U]\n\n[CODE]\n...something else...\n[U]inside the code tags[/U]\n\n...something else...\n[/CODE]";
preg_match_all("/\[CODE\]((?!\[\/?CODE\]).)*\[U\].*?\[\/CODE\]/s", $input, $matches);
print_r($matches[0]);
Array
(
[0] => [CODE]
...something else...
[U]inside the code tags[/U]
...something else...
[/CODE]
)
关于 PHP 代码本身不需要过多提及,除了我们使用 s
标志和 preg_match_all
,以确保我们 运行 中的正则表达式全点模式。这是必需的,因为您的内容跨越多行。
这里是对所用正则表达式的解释:
\[CODE\] match an initial [CODE] tag
((?!\[\/?CODE\]).)* consume anything so long it is not an opening OR closing [/CODE] tag
\[U\] consume an opening [U] tag
.*? then consume anything up until the first
\[\/CODE\] closing [/CODE] tag
上面的大部分正则表达式都很简单,除了以下部分:
((?!\[\/?CODE\]).)*
这使用了一种叫做 tempered 点的东西,它表示一次向前迈出一步,在每一步检查我们没有遇到空位 [CODE]
或关闭 [/CODE]
标签。这确保我们匹配 [CODE]...[/CODE]
标签集中的 [U]
标签。
请注意,我的回答假设您的输入格式正确,即除了您向我们展示的内容之外没有标签嵌套,并且每个开始标签都有一个适当的结束标签。如果您需要在此基础上进行验证,那么您将不得不做更多的工作。