У вас есть два входных файла. Один состоит из:
some text
insertion point pattern
rest of the text
плюс список чередующихся строк заголовка и автора во втором файле.
И вывод должен быть:
some text
insertion point pattern
...alternating list of title and author <div>s
rest of the text
Я думаю, что самый простой способ справиться с этим:
- Обработка списка заголовков / авторов (из файла
title.authors
) во временный файл.
- Пусть
sed
прочитает временный файл в точке вставки.
Это переводится в схему:
tmp=${TMPDIR:-/tmp}/at.$$ # Or use mktemp command
trap "rm -f $tmp; exit 1" 0 1 2 3 13 15
sed -e 'N' \
-e 's%\(.*\)\n\(.*\)%<div class="title">\1</div>\n<div class="author">\2</div>%' \
title.authors > $tmp
sed "/insertion point pattern/r $tmp" main-file > output-file
rm -f $tmp
trap 0
Сведения с помощью команд trap
гарантируют, что сценарий очищается после себя, если ему отправляется сигнал HUP, INT, QUIT, PIPE или TERM.
Первый скрипт sed
использует N
для объединения соседних строк, поэтому он дает заголовок и автора в двух строках в пространстве образца. Затем другая строка собирает материал с обеих сторон новой строки в \1
и \2
, которые затем помечаются.
Второй сценарий sed
определяет точку вставки, печатает эту строку, читает предварительно обработанный файл заголовков и авторов (обратите внимание на двойные кавычки, чтобы оболочка могла расширяться $tmp
) непосредственно перед чтением следующей строки.
Требовать временного файла - небольшая неприятность, но при этом четко разделяются различные обязанности по «форматированию заголовка и информации об авторе» и «копированию форматированного заголовка и информации об авторе в правильное место в потоке данных.
Если вам нужен маркер HTML / XML комментариев в выводе, вы можете усложнить свой сценарий предварительной обработки с помощью:
-e '1i\
<!-- above here is source file, below is sed'ed output -->' \
-e '$a\
<!-- below is rest of source file -->'
Имейте в виду, что ведущие пробелы будут включены в вывод. Если это имеет значение, поместите весь первый скрипт в файл (title-author.sed
) и используйте sed -f title-author.sed title.authors > $tmp
для предварительной обработки информации:
название-author.sed
1i\
<!-- above here is source file, below is sed'ed output -->
$a\
<!-- below is rest of source file -->
N
s%\(.*\)\n\(.*\)%<div class="title">\1</div>\n<div class="author">\2</div>%
Недостатком этого является дополнительный файл - скрипт sed. Конечно, вы можете создать его на лету как другой временный файл. Мой трюк заключается в использовании:
tmp=${TMPDIR:-/tmp}/at.$$
trap "rm -f $tmp.?; exit 1" 0 1 2 3 13 15
cat > $tmp.1 <<'EOF'
1i\
<!-- above here is source file, below is sed'ed output -->
$a\
<!-- below is rest of source file -->
N
s%\(.*\)\n\(.*\)%<div class="title">\1</div>\n<div class="author">\2</div>%
EOF
sed -f $tmp.1 title.authors > $tmp.2
sed "/insertion point pattern/r $tmp.2" main-file > output-file
rm -f $tmp.?
trap 0
Изменение заключается в использовании сгенерированного временного имени в качестве префикса, а фактические временные файлы $tmp.1
, $tmp.2
. Очистка незначительно отличается, чтобы отразить, что может быть несколько временных файлов для удаления.
Очевидно, что вы можете настроить параметры двух входных файлов в качестве сценария и просто оставить запись сценария в стандартном выводе, чтобы можно было перенаправить его вывод в любое место, вместо принудительного ввода output-file
. На самом деле это должен делать скрипт общего назначения.