Вопрос или проблема
Моя ситуация проста: у меня есть HTML-файл с несколькими строками, содержащими только <section>
блок-тег, каждая строка сопровождается (также с отступом) <h3 id="YYYY">...</h3>
тегом заголовка.
Вот так:
<section>
<h3 id="2024"><a href="index.fr.html#2024">fr</a> 2024 <a href="index.html#2024">en</a></h3>
При использовании привязанной ссылки для перехода к конкретному году на странице (или его переводу), титул года скрывается за <header>
.
Проблема будет решена путем перемещения атрибута id
на одну строку выше, от <h3>
к тегу <section>
,
вот так:
<section id="2024">
<h3><a href="index.fr.html#2024">fr</a> 2024 <a href="index.html#2024">en</a></h3>
Есть ли простая однострочная команда, которая позволила бы мне переместить все эти атрибуты id
из тега <h3>
в тег <section>
на одну строку выше? Я не нашел, как сопоставить несколько строк в BSD
sed
или особенно в awk
.
sed 's:<section>\(\s*\)<h3\( id="\[0-9\]{4}"\):<section\2>\1<h3:g' index.html
не изменяет файл. Также не сработает \n\t\t
вместо \s
или использование двойных обратных слэшей.
Есть ли опция для сопоставления пробельных символов, как я предполагаю, GNU
sed
будет делать? Только, возможно, вставка/использование новых строк/табуляций прямо в команде, но я хотел бы лучше разобраться и также вынужден, так как работаю удаленно и должен использовать termux
на Android
… Также я не обладаю достаточными навыками для использования обхода с помощью awk
.
Бессмысленный файл с совпадающими и не совпадающими строками, а также пара строк, которые уже имеют правильный формат:
$ cat index.html
<html>
<section>
<h2 id="2023"><a href="index.fr.html#2023">fr</a> 2023 <a href="index.html#2023">en</a></h3>
<section>
<h3 id="2024"><a href="index.fr.html#2024">fr</a> 2024 <a href="index.html#2024">en</a></h3>
<section id="2025">
<h3><a href="index.fr.html#2025">fr</a> 2025 <a href="index.html#2025">en</a></h3>
</html>
Хотя это может быть возможно сделать с помощью sed
, мои навыки sed
не на высоте.
Хотя автор вопроса заявил – Я не обладаю достаточными навыками для использования обхода с помощью awk
– вопрос был помечен тегом awk
, так что я попробую решить задачу с помощью awk
…
awk -F'[<>]' ' # разделить по двойным разделителям "<" и ">"
$2 == "section" { line1 = $0 # если 2-е поле "section", сохранить текущую строку
if (getline && $2 ~ /^h3 id=/) { # прочитать следующую строку, и если 2-е поле начинается с "h3 id=", тогда ...
match($2,/id=.*$/) # найти строку "id=..."
id = substr($2,RSTART,RLENGTH) # сохранить указанную строку
sub(/<section>/,"<section " id ">",line1) # обновить переменную "line1"
sub("<h3 " id ">","<h3>") # обновить текущую строку
}
print line1 # напечатать "line1"
}
1 # напечатать текущую строку
' index.html
Это генерирует:
<html>
<section>
<h2 id="2023"><a href="index.fr.html#2023">fr</a> 2023 <a href="index.html#2023">en</a></h3>
<section id="2024">
<h3><a href="index.fr.html#2024">fr</a> 2024 <a href="index.html#2024">en</a></h3>
<section id="2025">
<h3><a href="index.fr.html#2025">fr</a> 2025 <a href="index.html#2025">en</a></h3>
</html>
Ответ или решение
Ваш запрос о том, как переместить атрибут id
из тега <h3>
в тег <section>
в HTML-файле, требует корректного использования инструментов обработки текста, таких как sed
и awk
. Давайте разберем вашу задачу более подробно и предложим решение, подходящее для использования в среде BSD.
Проблема
У вас есть HTML-файл, в котором теги <h3>
содержат атрибут id
, и вы хотите переместить этот атрибут в тег <section>
, расположенный выше. Это действие поможет исправить проблему с наложением заголовков на (или загораживанием) других элементов интерфейса на странице.
Пример строки до изменения:
<section>
<h3 id="2024"><a href="index.fr.html#2024">fr</a> 2024 <a href="index.html#2024">en</a></h3>
</section>
Необходимый результат:
<section id="2024">
<h3><a href="index.fr.html#2024">fr</a> 2024 <a href="index.html#2024">en</a></h3>
</section>
Решение с использованием awk
Хотя sed
может использоваться для проблемы, awk
часто предоставляет больший контроль при обработке многострочных шаблонов, особенно когда необходимо взаимодействовать с данными, расположенными на нескольких строках. Вот работающий пример скрипта на awk
, который выполнит вашу задачу.
Команда awk
awk -F'[<>]' '
$2 == "section" {
line1 = $0 # Запоминает текущую строку для тега <section>
if (getline && $2 ~ /^h3 id=/) { # Проверяет, если следующая строка - <h3 id="...">
match($2, /id="[^"]+"/) # Находит id атрибут
id = substr($2, RSTART, RLENGTH) # Сохраняет id
sub(/<section>/, "<section " id ">", line1) # Добавляет id в тег <section>
sub(/ id="[^"]+"/, "", $0) # Удаляет id из тега <h3>
}
print line1 # Выводит модифицированный <section>
print $0 # Выводит модифицированный <h3>
next # Переходит к следующей строке
}
1 # Обрабатывает остальные строки без изменений
' index.html
Объяснение:
-F'[<>]'
: Устанавливает разделитель на<
и>
, что позволяет легко извлекать содержимое тега.$2 == "section"
: Проверяет, что текущая строка является тегом<section>
, затем сохраняет её в переменнойline1
.if (getline && $2 ~ /^h3 id=/)
: Используетgetline
для перехода к следующей строке и проверяет, является ли она тегом<h3>
с атрибутомid
.match($2, /id="[^"]+"/)
: Использует функциюmatch
для извлечения значенияid
.sub(/<section>/, "<section " id ">", line1)
: Модифицирует строкуline1
, добавляя найденныйid
.sub(/ id="[^"]+"/, "", $0)
: Удаляетid
из текущей строки<h3>
.print line1
иprint $0
: Печатает обновленные строки.1
: Условие, которое всегда истинно, заставляетawk
напечатать остальные строки без изменений.
Заключение
С помощью данной команды awk
вы сможете переместить атрибут id
из тега <h3>
в тег <section>
, что устранит проблему с наложением заголовка. Убедитесь, что ваш HTML-файл имеет правильный формат перед запуском команды, чтобы избежать неожиданных результатов. Если у вас возникнут дополнительные вопросы или потребуется поддержка, пожалуйста, не стесняйтесь обращаться за помощью.