PHP获取字符串形式的html注释并将其换行<;预处理>;标签。正则表达式还是DOM?

PHP获取字符串形式的html注释并将其换行<;预处理>;标签。正则表达式还是DOM?,php,regex,html,Php,Regex,Html,我想在字符串中查找注释标记,这些标记不在标记中,并将它们包装在标记中 <!-- Comment 1 --> <pre> <div class="some_html"></div> <!-- Comment 2 --> </pre> <!-- (?:(?!-->).)*--> 似乎无法使用PHPDOM“查找”注释 我已经在使用regex做一些处理,但是我对regex中的lookahead

我想在字符串中查找注释标记,这些标记不在
标记中,并将它们包装在
标记中

<!-- Comment 1 -->

<pre>
    <div class="some_html"></div>
    <!-- Comment 2 -->
</pre>
<!-- (?:(?!-->).)*-->
似乎无法使用PHPDOM“查找”注释

我已经在使用regex做一些处理,但是我对regex中的lookaheads和lookbehinds非常不熟悉(还没有掌握或真正理解)

例如,我可能有以下代码

(?=(?:(?!</?pre>).)*(?:</?pre>(?:(?!</?pre>).)*</?pre>(?:(?!</?pre>).)*)*$)

我想将注释1包装在
标记中,但显然不是注释2,因为它已经位于

<?php
$text = '<!-- Comment 1 -->

        <pre>
            <div class="some_html"></div>
            <!-- Comment 2 -->
        </pre>';

echo  "<div>Original Text: <xmp>$text</xmp></div>";

$html = str_get_html($text);

$comments = $html->find('comment');

// if find exists
if ($comments) {

  echo '<br>Find function found '. count($comments) . ' results: ';

  foreach($comments as $key=>$com){
    echo '<br>'.$key . ': ' . $com->tag . ' wich contains = <xmp>' . $com->innertext . '</xmp>';
  }
}
else
  echo "Find() fails !";
?>
$xpath = new DOMXpath($doc);

foreach($xpath->query('//comment()[not(ancestor::pre)]') as $comment){
  $pre = $doc->createElement("pre");
  $comment->parentNode->insertBefore($pre, $comment);
  $pre->appendChild($comment);
}
在正则表达式中通常是如何实现的

以下是我对消极环顾四周的理解,我尝试消极环顾四周,显然我做错了什么


(?*??(!*?)

如果您计划重新使用此代码,您应该真正使用DOM解析器。每一种正则表达式方法在使用现实世界的HTML时都会很快失败

话虽如此,以下是您可以(但不应该)做的事情:

首先,确定评论,例如使用

)*-->
负前瞻块确保。*不会超出注释块

现在,您需要确定此注释是否在
块中。这里的关键观察结果是,每个注释后面都有偶数个
元素,这些元素尚未包含在一条注释中

<!-- Comment 1 -->

<pre>
    <div class="some_html"></div>
    <!-- Comment 2 -->
</pre>
因此,请始终成对地浏览课文的其余部分,并检查是否到达结尾

这看起来像

(?=(?:(!))*(?:(?:(!))*(?:(!)*)*$)
所以,这将是

*-->((?=(?:(?!))*(?:(?!))*(?:(?!))*(?:(?!))*)*$) 只写代码=)的万岁

此表达式的主要组成部分是
(?:(?!)
,它匹配不是
序列起始括号的每个字符

允许
上的属性和正确转义留给读者作为练习。请在中查看此操作

似乎无法使用PHPDOM“查找”注释

你当然可以。。。使用以下命令检查此代码:


$com->innertext
将给您提供类似

你现在只需要按照你的意愿清洗它们。例如,使用
。。。试试看

编辑: 只是一个关于查找的注释,它必须有一个固定的宽度,因此不能使用重复
*+
或可选项

坏消息是,大多数正则表达式风格不允许您在lookback中只使用任何正则表达式,因为它们不能向后应用正则表达式。因此,正则表达式引擎需要能够在检查lookback之前计算出要后退多少步

因此,许多正则表达式风格,包括Perl和Python使用的那些,只允许固定长度的字符串。您可以使用任何可以预先确定匹配长度的正则表达式。这意味着您可以使用文字文本和字符类。不能使用重复项或可选项。您可以使用替换,但前提是替换中的所有选项都具有相同的长度

资料来源:

Xpath是您的朋友:


这很容易,使用一种称为堆栈计数器的原理,
基本上,您可以计算
标记的数量和
标记的数量,直到您的段放置在HTML代码中的点为止
如果
,这意味着“
。--您在这里--

在这种情况下,只需返回匹配项,未修改的-就这么简单。

相反。或者。这些“链接”都不能回答问题。我将提出一些我试图使问题更具体的东西。如果可能的话,我宁愿不使用外部库。您是否直接控制输入HTML,以便确保没有包含
的JavaScript或注释,没有CDATA块,也没有嵌套注释或
块?如果您不能确保这一点,那么使用regex可能没有合理的解决方案。如果可以的话,我将尝试给出one=)@Joel正则表达式的问题是,PCRE不支持可变长度的lookbehind。因此,尽管您的尝试实际上相当合理(除了一些贪婪问题),但它只在.NET中有效。这就是为什么用正则表达式几乎不可能解决这个问题。不使用本机PHP DOM类尽管您建议不实际使用此方法,但我会将此标记为答案,因为它简洁地回答了我的问题re:regex,并且非常有用。谢谢!:)