хочу заменить строку с помощью sed

Вопрос или проблема

У меня есть HTML-файл, и я хочу заменить строку, включенную между двумя тегами HTML-таблицы. Вот пример того, что у меня есть:

<tr class="noBorder"><td>string1</td><td>string2</td><td>string3</td><td>string4</td><td>random string</td></tr>

Итак, я хочу заменить только случайную строку на что-то другое только в одной конкретной строке. В моей таблице это последняя ячейка.

Я пробую это;
sed -e '28s/\(<td>\).*\(<\/td><\/tr>\)/<td>!!variable instead of random!!<\/td><\/tr>/' file.html

Но это заменяется на следующее (так что я теряю все перед этим);

<tr class="noBorder"><td>!!variable вместо random!!</td></tr>

Я хочу это;

<tr class="noBorder"><td>string1</td><td>string2</td><td>string3</td><td>string4</td><td>!!variable вместо random!!</td></tr>

Спасибо всем, кто может это решить

Не используйте регулярные выражения для парсинга HTML. Используйте парсер HTML.

Учитывая следующее:

<!DOCTYPE html>
<html>
<head>
    <title>Foo</title>
</head>
<body>
    <!-- Таблица "foo" -->
    <table id="foo">
        <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr>
        <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr>
        <tr><td>Col1</td><td>Col2</td><td>Col3</td></tr>
    </table>
</body>
</html>

Чтобы заменить содержимое последней ячейки второй строки в таблице foo, используя xmlstarlet, вы должны сделать:

xmlstarlet ed -u '//table[@id="foo"]/tr[2]/td[last()]' -v 'Replacement' page.html | sed 1d
  • //table[@id="foo"]: адресует все таблицы с id foo (которых у вас, кстати, должно быть только одна)
  • /tr[2]: адресует второй элемент tr
  • /td[last()]: адресует последний элемент td

Команда sed '1d', к сожалению, необходима, потому что xmlstarlet вставит тег версии XML в начало. Я не нашел способа предотвратить это.

Также имейте в виду, что форматирование документа может измениться как побочный эффект парсинга:

% xmlstarlet ed -u 'html/body/table[@id="foo"]/tr[2]/td[last()]' -v 'Replacement' page.html | sed 1d
<!DOCTYPE html>
<html>
  <head>
    <title>Foo</title>
  </head>
  <body>
    <!-- Таблица "foo" -->
    <table id="foo">
      <tr>
        <td>Col1</td>
        <td>Col2</td>
        <td>Col3</td>
      </tr>
      <tr>
        <td>Col1</td>
        <td>Col2</td>
        <td>Replacement</td>
      </tr>
      <tr>
        <td>Col1</td>
        <td>Col2</td>
        <td>Col3</td>
      </tr>
    </table>
  </body>
</html>

Ответ или решение

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

При работе с HTML-файлами и необходимости замены строки, особенно в контексте таблиц, важно помнить, что sed не лучший выбор для манипуляций с HTML-структурой. В этой статье мы подробно обсудим, как использовать sed для замены строки в конкретной ячейке таблицы. Тем не менее, рекомендуется воспользоваться специализированными инструментами для работы с XML или HTML, такими как xmlstarlet, для более надежных и чистых решений.

Пример исходной HTML-структуры

Предположим, у вас есть следующая HTML-структура, и вам нужно заменить текст "random string" в последней ячейке второго ряда таблицы:

<tr class="noBorder">
    <td>string1</td>
    <td>string2</td>
    <td>string3</td>
    <td>string4</td>
    <td>random string</td>
</tr>

Замена строки с помощью sed

Вы пытаетесь выполнить следующую команду sed:

sed -e '28s/\(<td>\).*\(<\/td><\/tr>\)/<td>!!variable instead of random!!<\/td><\/tr>/' file.html

К сожалению, эта команда упускает часть строки и приводит к потере содержимого предыдущих ячеек. Вместо этого вы можете попробовать более детальный и точный подход:

sed -i '28s/\(.*<td>\)[^<]*\(.*<\/td>\)/\1!!variable instead of random!!\2/' file.html
Объяснение команды:
  • -i — Этот параметр позволяет редактировать файл на месте.
  • 28s/ — Выбор 28-й строки для замены. Убедитесь, что в вашем файле есть достаточное количество строк, чтобы эта команда не выдавала ошибку.
  • \(.*<td>\) — Указывает на любой текст перед необходимой ячейкой.
  • [^<]* — Захватывает текст внутри ячейки, не включая символы <.
  • \(.*<\/td>\) — Указывает на любой текст после ячейки вплоть до </td>.

Таким образом, команда сохраняет все содержимое перед и после целевой ячейки, заменяя только нужное значение.

Альтернатива — Использование xmlstarlet

Если структура документа более сложная или если вам нужно обрабатывать файлы HTML и XML более надежно, рассмотрите использование xmlstarlet. Например, для замены содержимого последней ячейки второго ряда таблицы можете использовать следующую команду:

xmlstarlet ed -u '//table[@id="foo"]/tr[2]/td[last()]' -v '!!variable instead of random!!' file.html | sed '1d'
Объяснение команды:
  • //table[@id="foo"] — Выбор таблицы с указанным идентификатором.
  • /tr[2] — Обращение ко второму ряду таблицы.
  • /td[last()] — Выбор последней ячейки текущего ряда.
  • sed '1d' — Удаление первой строки вывода, которую добавляет xmlstarlet.

Заключение

При работе с HTML-структурами целесообразно использовать более специализированные инструменты, чем sed, для предотвращения ошибок при парсинге. Несмотря на возможность замены через sed, использование xmlstarlet дает большую уверенность в корректности манипуляций с разметкой и сохранением других данных. Помните, что изменение HTML и XML документации требует осторожности и внимательности к структуре данных.

Оцените материал
Добавить комментарий

Капча загружается...