【问题标题】:PHP regex - capturing content between two strings (multiple results)PHP regex - 捕获两个字符串之间的内容(多个结果)
【发布时间】:2017-05-10 20:29:28
【问题描述】:

花了超过 2.5 小时后,有人可以帮忙吗?

我的 html 文件格式如下:

示例 1

[[section_abc]]
<div>
several lines of html ...
</div>
[[/section_abc]]

示例 1

[[section_opq]]
<div>
several lines of html ...
</div>
[[/section_opq]]

以下是所需的输出: 示例 1: 第一组:section_abc group2:[[section_abc]][[/section_abc]] 之间的内容

示例 2: 第一组:section_opq group2:[[section_opq]][[/section_opq]] 之间的内容

这是我目前的测试线:

preg_match_all("/(\[\[)([^}]+)(\]\])/", $input_lines, $output_array);

【问题讨论】:

  • 你的代码在哪里?什么不工作?

标签: php regex preg-match-all


【解决方案1】:

这种模式可能会起作用(最小):

\[{2}([^\W]+)\]{2}\n([^[]+)

结果

匹配 1

第一组:

section_abc

第二组:

<div>
several lines of html ...
<more><a href=""></a>
</div>`

第 2 场比赛

第一组:

section_opq

第二组:

<div>
several lines of html ...
<more><a href=""></a>
</div>

示例

https://regex101.com/r/lCX9FA/1

【讨论】:

  • 这个肯定更整洁。
【解决方案2】:

如果没有部分嵌套,试试

preg_match_all('~\[\[(\w+)]]((?>[^[]+|\[[^[])*)\[\[/\1]]~s', $str, $out)

php demo at eval.inregex demo at regex101

【讨论】:

  • 如果您使用(?&gt;[^[]+|\[[^[])*,则使用捕获和反向引用没有意义。在替换的第二部分中,您只需确保最终的左方括号后面没有另一个左方括号 (regex101.com/r/7zbI5i/1),但是由于您使用了结束标记的反向引用,您可以做更多:您可以确保开始方括号不是结束标记的开始(或最终嵌套的相同标记)。为此,您只需编写:(?&gt;[^[]+|\[(?!\[/?\1\b))*,可以改进为[^[]*+(?:\[(?!\[/?\1\b)[^[]*)*+ (展开模式)
  • 感谢您的意见@CasimiretHippolyte。实际上正要发布与您的建议类似的内容,但后来认为这可能超出了需要。第一种模式不适用于嵌套部分,但允许类似a[b]c(包括recursive version 然而,that would also work for such case)。这两种模式都是为了匹配整个部分(直到[[/section_abc]]),因为我不知道以后会如何使用它。 +1 为您的评论。随意编辑我的答案。
【解决方案3】:

这就是你要找的东西:

/(?&lt;=\[\[(section_\w{3})\]\])(.+)(?&gt;\[\[\/\1\]\])/s

分解正则表达式

  1. (?&lt;=\[\[(section_\w{3})\]\]) 提供后向匹配以匹配以 [[section_foo]] 开头的字符串,但不包含标记
  2. (.+) 捕获标签内的所有内容
  3. (?&gt;\[\[\/\1\]\]) 提供前瞻匹配以相同 [[/section_foo]] 标记结尾但不包含标记的字符串(注意:\1 是对第一个捕获组的引用,即标记名)
  4. /s 使点 . 匹配换行符(请注意,在当前正则表达式中,在开始和结束标记之前的换行符包含在匹配中)

结果

示例 1:

第 1 组:section_abc

第 2 组:

<div>
several lines of html ...
</div>

示例 2:

第一组:section_opq

第 2 组:

<div>
several lines of html ...
</div>

【讨论】:

  • 非常接近。部分命名并不总是 section_ 后跟 3 个字符。它可能是 section_something 或 employee_data 等。有什么建议吗?谢谢
【解决方案4】:

怎么样:

(\[\[[^\]]+\]\])([^\[]+)(\[\[[^\]]+\]\])

第 1 组将包含开始标签
第 2 组将包含数据块
第 3 组将包含结束标记

【讨论】:

    猜你喜欢
    • 2012-11-06
    • 2010-11-29
    • 1970-01-01
    • 2015-06-24
    • 2016-12-06
    • 2020-11-30
    • 2013-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多