【问题标题】:Grab all text between nested matching characters recursively递归地抓取嵌套匹配字符之间的所有文本
【发布时间】:2018-05-13 21:17:09
【问题描述】:

这是一个示例输入字符串:

((#1662# - #[Réz-de-chaussée][Thermostate][Temperature Actuel]#) > 4) && #1304# == 1 and #[Aucun][Template][ReviseConfort#templateSuffix#]#

这些是必需的输出字符串:

#1662#
#[Réz-de-chaussée][Thermostate][Temperature Actuel]#
#1304#
#[Aucun][Template][ReviseConfort#templateSuffix#]#

我试过这个正则表达式,但它不起作用:

~("|\').*?\1(*SKIP)(*FAIL)|\#(?:[^##]|(?R))*\#~

【问题讨论】:

  • 很抱歉,我在第一次编辑时的示例包含错误。前后分隔符是#。
  • 恐怕您的问题不清楚,因为您的模式尝试匹配的内容与示例输入之间存在明显差异。请通过提供更真实的示例输入(或更好的示例输入s,更好地代表您将遇到的字符串类型)来改进您的问题。

标签: php regex preg-match-all


【解决方案1】:
preg_match_all( '/\#((\d{1,4})|(\[[^0-9]+\]))[\#$]/'
              , '((#1662# - #[Réz-de-chaussée][Thermostate][Temperature Actuel]$) > 4) && #1304$ == 1 and #[Aucun][Template][ReviseConfort#templateSuffix#]#'
              , $matches
              );
foreach($matches[0] as $match)
    echo $match.PHP_EOL;

【讨论】:

    【解决方案2】:

    试试这个(?:#[^#[]+#|##(?:.+?]#){2}|#(?:.+?]#){1})

    解释:

    (?: // 抓取 1 个开始 # 和 1 个结束 # 标记之间不是 #[ 字符的所有内容 #[^#[]+#| // 抓取 2 个开始 # 和 2 个结束 ]# 标签之间的所有内容 ##(?:.+?]#){2}| // 抓取 1 个开始 # 和 1 个结束 ]# 标记之间的所有内容 #(?:.+?]#){1} )

    【讨论】:

    • 它工作正常,但不适用于这个 ##foreach[name]#[Off]# 返回是 ##foreach[name]# 而不是 ##foreach[name]#[Off]#
    • 适应新情况,立即查看
    【解决方案3】:

    这种情况并不特别适合递归。最好使用普通的正则表达式。

    很难确定以下内容是否适用于所有其他可能的输入,因为您只提供了两个有限的示例。

    至少在这些示例中,所需的结束 # 后跟 )、空格或行尾。对这些值使用负前瞻允许我们捕获内部嵌套的#:

    #(?:[^#]|#(?![\s)]|$))+#
    

    Demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-14
      • 2021-12-15
      • 1970-01-01
      相关资源
      最近更新 更多