Добавить текст между несколькими строками с sed, если предыдущая строка не соответствует шаблону

Я пытаюсь добавить теги <dl> вокруг списка определений с помощью sed, и, возможно, есть более простой способ сделать это (я хотел бы узнать).

Я хотел бы искать файл для любых строк, содержащих <dt> , но только в том случае, если предыдущая строка не содержит <dt> или <dd> . Когда совпадение найдено, вставьте <dl> .

Моя попытка до сих пор (что совсем не совпадает):

 sed '/^((?!<dt>).)*$/ { N /<dt>/ { s/<dt>/<dl><dt>/ } }' file 

И файл

 # TODO # * Set up mail transfer agent * Reconfigure timezone ```bash dpkg-reconfigure tzdata ``` # Hardware # <dt>RAM</dt> <dd>2GB</dd> # Partitions # <dt>`/dev/sda1`</dt> <dd>/boot</dd> <dt>`/dev/sda2`</dt> <dd>/</dd> 

Цель всего этого – написать парсер, который преобразует разметку wiki moinmoin в markdown, для переноса на новый движок вики. Список исправлений в настоящее время выполняется со следующим правилом:

 sed -i 's/^ \(.*\):: \(.*\)$/ <dt>\1<\/dt>\n <dd>\2<\/dd>/' file 

Я хотел бы, чтобы результат выглядел так:

 # TODO # * Set up mail transfer agent * Reconfigure timezone ```bash dpkg-reconfigure tzdata ``` # Hardware # <dl> <dt>RAM</dt> <dd>2GB</dd> </dl> # Partitions # <dl> <dt>`/dev/sda1`</dt> <dd>/boot</dd> <dt>`/dev/sda2`</dt> <dd>/</dd> </dl> 

Обратите внимание, что я хотел бы как можно больше использовать html. Для каждого открывающего тега должен быть закрывающий тег.

One Solution collect form web for “Добавить текст между несколькими строками с sed, если предыдущая строка не соответствует шаблону”

Это может быть больше, чем вы ожидаете, но я думаю, что это лучший способ выполнить то, что вы хотите с sed .

Этот скрипт:

  • Вставляет строку <dl> перед каждой строкой, содержащей <dt> , если перед этой строкой не было других <dt> , <dd> или <dl> .

  • Добавляет строку </dl> после каждой строки, содержащей <dd> , если строка после строки, содержащей <dd> , не содержит <dd> .

Этот скрипт sed использует пространство hold sed чтобы запомнить предыдущую строку, чтобы его можно было проверить для тегов <d[tdl]> прежде чем вставлять <dl> . Он также использует относительную адресацию ADDR,+N чтобы добавить тэг закрытия </dl> . Для определения того, находится ли <dd> в последней строке файла и требуется прилагаемый </dl> требуется специальный случай. Тестирование ( t и T ) и ветвление ( b ) широко используются для реализации логики.

 #!/bin/sh sed ' /<dt>/ { x # exchange pattern and hold space s/<d[tdl]>// # subsitutue, just testing for pattern g # copy hold space back, overwriting pattern space t end # branch to :end if previous subsitution successful i \ <dl> } $ { /<dd>/ ! b end # if <dd> on last line, append </dl> a \ </dl> } /<dd>/,+1 { # on each line containing <dd> and the line after /<dd>/ b end # if does not contain <dd>, insert </dl> i \ </dl> } :end h # copy pattern space to hold space for next round ' "$@" 

Этот скрипт изменяет образцы данных таким образом:

 [...] # Hardware # <dl> <dt>RAM</dt> <dd>2GB</dd> </dl> # Partitions # <dl> <dt>`/dev/sda1`</dt> <dd>/boot</dd> <dt>`/dev/sda2`</dt> <dd>/</dd> </dl> 
  • подмножество файла для правильных хромосом
  • Почему * соответствует, где нет цифр?
  • Как использовать sed, awk или grep для удаления определенного шаблона, но все остальное
  • вырезать первый и последний элемент в CSV
  • Извлечение жетонов из строки текста
  • Как добавить текст в конец строки, содержащей несколько строк?
  • Найти шаблон и удалить его из всех файлов
  • Как я могу эффективно выбирать конкретные номера строк из списка записей?
  • Скользящее среднее в файле журнала с awk или другими утилитами unix?
  • Задача сравнения регулярных выражений / шаблонов для извлечения данных
  • Замена строк в файлах с содержимым файла
  • Linux и Unix - лучшая ОС в мире.