【问题标题】:what is the wrong of this regex pattern for nested {* *}?这个嵌套 {* *} 的正则表达式模式有什么问题?
【发布时间】:2013-03-26 17:21:01
【问题描述】:

我有这个 HTML 文档

{*
<h2 class="block_title bg0">ahmooooooooooooooooooooooooooooooooooooooooooodi</h2>
<div class="block_content padding bg0">{welc_msg}</div>
<br/>
    {*
    hii<br /><span>5
    *}

    {*
    hii<br /><span>5

    *}
*}

我想删除它,所以我想删除{* *}之间的任何东西

我写了正则表达式模式:

preg_replace("#(\{\*(.*?)\*\})+#isx",'',$html);

它可以工作,但它不能 100% 理想地工作,它最后会留下 *}

你能告诉我真正的模式吗?

【问题讨论】:

  • 您需要使用recursive regex 来匹配嵌套结构吗?
  • 请问如何?我之前没有写递归正则表达式
  • 您的嵌套模式语言不是regular。因此,您不能使用(普通)正则表达式。但是你可以在这里使用PCRE supports recursive patterns

标签: php regex preg-replace pattern-matching


【解决方案1】:

如果您的正则表达式引擎支持匹配嵌套结构(PHP 支持),那么您可以像这样一次性删除(可能是嵌套的)元素:

一次性应用递归正则表达式:

function stripNestedElementsRecursive($text) {
    return preg_replace('/
        # Match outermost (nestable) "{*...*}" element.
        \{\*        # Element start tag sequence.
        (?:         # Group zero or more element contents alternatives.
          [^{*]++   # Either one or more non-start-of-tag chars.
        | \{(?!\*)  # or "{" that is not beginning of a start tag.
        | \*(?!\})  # or "*" that is not beginning of an end tag.
        | (?R)      # or a valid nested matching tag element.
        )*          # Zero or more element contents alternatives.
        \*\}        # Element end tag sequence.
        /x', '', $text);
}

上述递归正则表达式匹配最外层 {*...*} 元素,该元素可能包含嵌套元素。

但是,如果您的正则表达式引擎不支持匹配的嵌套结构,您仍然可以完成工作,但您无法一次性完成。可以制作匹配 innermost {*...*} 元素的正则表达式(即不包含任何嵌套元素的正则表达式)。这个正则表达式可以以递归方式应用,直到文本中不再有这样的元素:

递归应用非递归正则表达式:

function stripNestedElementsNonRecursive($text) {
    $re = '/
        # Match innermost (not nested) "{*...*}" element.
        \{\*        # Element start tag sequence.
        (?:         # Group zero or more element contents alternatives.
          [^{*]++   # Either one or more non-start-of-tag chars.
        | \{(?!\*)  # or "{" that is not beginning of a start tag.
        | \*(?!\})  # or "*" that is not beginning of an end tag.
        )*          # Zero or more element contents alternatives.
        \*\}        # Element end tag sequence.
        /x';
    while (preg_match($re, $text)) {
        $text = preg_replace($re, '', $text);
    }
    return $text;
}

使用正则表达式处理嵌套结构是一个高级主题,必须仔细阅读!如果有人真的想将正则表达式用于此类高级应用程序,我强烈建议阅读这方面的经典著作主题:Mastering Regular Expressions (3rd Edition) Jeffrey Friedl。老实说,这是我读过的最有用的书。

快乐的正则表达式!

【讨论】:

    【解决方案2】:

    您需要recursive regex 来匹配嵌套括号。它应该是这样的:

    "#(\{\*([^{}]*?(?R)[^{}]*?)\*\})+#isx"
    

    【讨论】:

    • 关闭,但如果元素包含孤立的 {,则 \{\*([^{}]*?(?R)[^{}]*?)\*\} 无法匹配,例如“{* won't match {these} contents *}”。
    • @ridgerunner:是的,我完全忽略了分隔符由两个字符组成:-/ 而不是修复它(并使正则表达式变得比现在更难读),我只会赞成你的回答!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-28
    相关资源
    最近更新 更多