Закомментируйте весь блок гиперссылки с помощью sed в файле HTML

Я хотел бы удалить некоторые гиперссылки, которые содержат «устаревшие/» в 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>), даже если они растягиваются на несколько строк.

Найдите -z на справочной странице sed.

Ed Morton 08.04.2019 18:58
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
1
1
67
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

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, не комментируется.

Спасибо за этот ответ. Я пробовал, но получил много ошибок. Я предполагаю, что, возможно, исходные файлы HTML не имеют строгой структуры.

Franklin 09.04.2019 07:51

@Franklin: не могли бы вы запустить команду xsltproc --html remove_legacy.xslt webpage.html с помощью --html?

Allan 09.04.2019 07:55

@Franklin: если и это не работает, то это потому, что ваши html-файлы повреждены ...

Allan 09.04.2019 07:55

Правильно, это должно быть проблемой исходного HTML-файла. pastebin.com/AqjxmDJT Первая ошибка в строке 7 содержит только <head>. Строка 138 — это строка кода javascript, вызывающая много ошибок. Также у него есть <g:sharetoclassroom>, который, я думаю, должен работать для класса Google. Спасибо, что поделились инструментом в любом случае.

Franklin 09.04.2019 08:33
Ответ принят как подходящий

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

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

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

попробуй гну сед

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

Другие вопросы по теме