【问题标题】:preg_match_all for nested elementpreg_match_all 用于嵌套元素
【发布时间】:2022-01-21 15:42:14
【问题描述】:

这是一种BB码。知道如何匹配所有元素,如 [LI]text[/LI] 和 [UL]text[/UL]?

preg_match_all("/(\[UL].*\[\/UL])|(\[LI].*\[\/LI])/", '[UL][LI]sadas[/LI][/UL]', $match);

想要收到类似的东西:

0 => "[UL][LI]sadas[/LI][/UL]"
1 => "[UL][LI]sadas[/LI][/UL]"
2 => "[LI]sadas[/LI]"    <--- This is not captured now.

基本上是关于:如何获得这个 [LI]text[/LI] 部分而不是松散 [UL]text[/UL] 部分?

【问题讨论】:

  • 条件的第一部分([UL])匹配,没有理由也匹配第二部分(嵌套[LI]
  • 它不会返回重叠的匹配项。
  • preg_match_all("~(\[UL](.*?)\[/UL]~s", '[UL][LI]sadas[/LI][/UL]', $match);

标签: php preg-match-all


【解决方案1】:

要做到这一点,你需要两件事:

  • 递归子模式(捕获组中引用自身的子模式)
  • 将此递归模式放入前瞻断言中(因为断言不消耗字符,并且使用此技巧,您可以多次匹配相同的子字符串)

~(?=(\[(\w+)]([^[]*(?:(?1)[^[]*)*?)\[/\2]))~

(?=...) 是先行断言。 (当前位置后跟...)
(\[(\w+)]([^[]*(?:(?1)[^[]*)*?)\[/\2])是捕获组1。
(?1)是指捕获组1内的子模式。
\2是指匹配的捕获组 2(标签名称)。

demo

【讨论】:

  • 虽然这并不能完全解决我的问题,但我用它来创建我需要的东西。没有你的帮助,我不会发现这一点,所以我接受这个回答。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-11
  • 2019-05-12
  • 1970-01-01
  • 2017-04-15
  • 1970-01-01
  • 2013-09-20
  • 1970-01-01
相关资源
最近更新 更多