用HTML文件中的s注释掉整个超链接块

时间:2019-04-08 11:56:12

标签: html sed multiline

我想删除某些HTML文件中URL中都包含“ legacy /”的某些超链接。但是,其中一些位于同一行

<a href=".../legacy/..."> ... </a>\n

而其他人则没有。如何使用sed一次替换它们?

到目前为止,我已经尝试过

sed -ri 's/(.+legacy\/[[:print:]]+<\/a>.*$)/<!--\1-->/g' wave-on-a-string.html 

仅替换一行中的超链接。然后,我意识到sed一次只能读取一行。但是,我找不到如何匹配多(行数)行超链接块的方法。

HTML文件具有如下内容:

      <a class="other-sim-page" href="legacy/wave-on-a-string.html" dir="ltr">
        <table>
          <tr>
            <td>
              <img style="display: block;" src="../../images/icons/sim-badges/flash-badge.png" alt="Flash Logo" width="44" height="44">
            </td>
            <td>
              <span class="other-sim-link">原始模擬教學與翻譯</span>
            </td>
          </tr>
        </table>
      </a>

...

          <p>瀏覽<a href="legacy/wave-on-a-string.html#for-teachers-header">更多活動</a>。</p>

...

                    <a href="legacy/radiating-charge.html" class="simulation-link">

                      <img class="simulation-list-thumbnail" src="../../sims/radiating-charge/radiating-charge-128.png" id="simulation-display-thumbnail-radiating-charge" alt="Screenshot of the simulation 電荷輻射" width="128" height="84"/><br/>
                        <strong><span class="simulation-list-title">電荷輻射</span></strong><br/>
                        <span class="sim-display-badge sim-badge-flash"></span>
                    </a>

...

,因为它在一行中,所以它仅匹配并替换第二个超链接。

如果所有超链接块(<a href="..."> ... </a>)跨越多行,我也希望替换它们。

3 个答案:

答案 0 :(得分:1)

使用-z的GNU sed,并使用您在一个文件中一起提供的所有3个输入块作为输入:

$ sed -z '
    s:@:@A:g; s:}:@B:g; s:</a>:}:g;
    s:<a[^<>]* href="legacy/[^}]*}:<!--&-->:g;
    s:}:</a>:g; s:@B:}:g; s:@A:@:g
' file
      <!--<a class="other-sim-page" href="legacy/wave-on-a-string.html" dir="ltr">
        <table>
          <tr>
            <td>
              <img style="display: block;" src="../../images/icons/sim-badges/flash-badge.png" alt="Flash Logo" width="44" height="44">
            </td>
            <td>
              <span class="other-sim-link">原始模擬教學與翻譯</span>
            </td>
          </tr>
        </table>
      </a>-->

...

          <p>瀏覽<!--<a href="legacy/wave-on-a-string.html#for-teachers-header">更多活動</a>-->。</p>

...

                    <!--<a href="legacy/radiating-charge.html" class="simulation-link">

                      <img class="simulation-list-thumbnail" src="../../sims/radiating-charge/radiating-charge-128.png" id="simulation-display-thumbnail-radiating-charge" alt="Screenshot of the simulation 電荷輻射" width="128" height="84"/><br/>
                        <strong><span class="simulation-list-title">電荷輻射</span></strong><br/>
                        <span class="sim-display-badge sim-badge-flash"></span>
                    </a>-->

通过将所有}转换为}s,然后将所有@B转换为第一行,</a>变成了字符,之后在输入中无法显示。放入}中,以便在要替换的字符串的正则表达式中,可以在方括号表达式中将{替换为[^}]中的char,第二行进行所需的实际替换,第三行恢复所有{ {1} s至} s,然后</a> s至@B s。

操纵输入以创建输入中不存在的char是一个相当常见的sed习惯用法,可以解决无法否定正则表达式中的字符串的问题。参见https://stackoverflow.com/a/35708616/1745001以获得另一个示例的更多说明。

如果输入中的字符串类似于您要匹配的字符串,这当然会失败,但实际上,对于您的特定输入来说可能已经足够了-您只需考虑一下它的功能并检查一下输出以进行验证。

答案 1 :(得分:0)

您没有使用正确的工具来完成此任务。

sed是使用正则表达式执行查找和替换的好工具,但是正则表达式(基于DFA)无法解析JSON或XML树之类的嵌套结构(因为嵌套深度没有限制) )。因此,我建议使用XML / HTML解析器。

例如,您可以使用XSLT

输入:

$ cat webpage.html 
<!DOCTYPE html>
<html>
    <body>
        <h1>My First Heading</h1>
        <p>My first paragraph.</p>
        <a href="https://www.w3schools.com">Visit W3Schools</a>
                <p>My second paragraph.</p>
        <a href="legacy/radiating-charge.html" class="simulation-link">
            <img class="simulation-list-thumbnail" src="../../sims/radiating-charge/radiating-charge-128.png" id="simulation-display-thumbnail-radiating-charge" alt="Screenshot of the simulation 電荷輻射" width="128" height="84"/><br/>
            <strong><span class="simulation-list-title">電荷輻射</span></strong><br/>
            <span class="sim-display-badge sim-badge-flash"></span>
        </a>
    </body>
</html>

样式表:

$ cat remove_legacy.xslt 
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

   <xsl:output method="html" encoding="UTF-8" omit-xml-declaration="yes"/>

   <!-- copy the whole structure recursively -->
    <xsl:template match="@*|node()">
       <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
       </xsl:copy>
    </xsl:template>

   <!-- when you meet a tag a that contains href -->
   <xsl:template match="//a[contains(@href,'legacy')]">
     <!-- add comment starting tag -->
     <xsl:text disable-output-escaping="yes">&#xa;&lt;!--&#xa;</xsl:text>
       <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
       </xsl:copy>
     <!-- add comment ending tag -->
     <xsl:text disable-output-escaping="yes">&#xa;--&gt;&#xa;</xsl:text> 
   </xsl:template>

</xsl:stylesheet>

输出:

$ xsltproc --html remove_legacy.xslt webpage.html 
<html>
    <body>
        <h1>My First Heading</h1>
        <p>My first paragraph.</p>
        <a href="https://www.w3schools.com">Visit W3Schools</a>
                <p>My second paragraph.</p>

<!--
<a href="legacy/radiating-charge.html" class="simulation-link">
            <img class="simulation-list-thumbnail" src="../../sims/radiating-charge/radiating-charge-128.png" id="simulation-display-thumbnail-radiating-charge" alt="Screenshot of the simulation 電荷輻射" width="128" height="84"><br>
            <strong><span class="simulation-list-title">電荷輻射</span></strong><br>
            <span class="sim-display-badge sim-badge-flash"></span>
        </a>
-->

    </body>
</html>

如您所见,不包含href的{​​{1}}没有被注释。

答案 2 :(得分:0)

尝试gnu sed

sed -E '/<a\s+.*href=.*legacy\/.*<\/a>/d; /<a\s+.*href=.*legacy\//,/<\/a>/d'  wave-on-a-string.html