Закомментируйте весь блок гиперссылок с помощью sed в файле HTML - PullRequest
1 голос
/ 08 апреля 2019

Я хотел бы удалить определенные гиперссылки, которые содержат "legacy /" в URL во многих файлах HTML. Тем не менее, некоторые из них находятся в одной строке

<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 ]

1 голос
/ 09 апреля 2019

С GNU sed для -z и использованием всех трех блоков ввода, которые вы предоставили вместе в одном файле, в качестве ввода:

$ 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> с в }, чтобы символ мог быть отвергнутым в выражении в скобках как [^}] в регулярном выражении для строки, которую вы хотите заменить, вторая строка выполняет фактическую замену, которую вы хотите, а третья строка восстанавливает все } s до </a> s и затем @B с } с.

Манипулирование вводом для создания символа, который не может существовать во вводе, является довольно распространенной идиотской формой, позволяющей обойтись без возможности отрицать строки в регулярных выражениях. См. https://stackoverflow.com/a/35708616/1745001 для другого примера с дополнительным объяснением.

Это, конечно, потерпит неудачу, если в вашем входе есть строки, которые похожи на строки, которые вы пытаетесь сопоставить, но в действительности это, вероятно, достаточно хорошо для вашего конкретного ввода - вам просто нужно подумать о том, что он делает, и проверить это вывод для проверки.

0 голосов
/ 13 апреля 2019

попробуйте GNU SED

sed -E '/<a\s+.*href=.*legacy\/.*<\/a>/d; /<a\s+.*href=.*legacy\//,/<\/a>/d'  wave-on-a-string.html 
0 голосов
/ 09 апреля 2019

Вы не используете подходящий инструмент для этой задачи.

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, который не содержит legacy, не являетсяпрокомментировал.

...