Как заменить часть текстового файла между маркерами другим текстовым файлом?

18204
smokris

Скажем, у меня есть текстовый файл, как это:

# custom content section a b  ### BEGIN GENERATED CONTENT c d ### END GENERATED CONTENT 

Я хотел бы заменить часть между GENERATED CONTENTтегами содержимым другого файла.

Какой самый простой способ сделать это?

22

4 ответа на вопрос

30
Peter.O
lead='^### BEGIN GENERATED CONTENT$' tail='^### END GENERATED CONTENT$' sed -e "/$lead/,/$tail/{ /$lead/; /$tail/p; d }" existing_file 
Отлично. `sed` может сделать гораздо больше, чем просто` s / ... / ... `! DevSolar 12 лет назад 0
Хммм не работает для меня, я должен поставить команду Sed в одну строку? lzap 10 лет назад 0
Команда `r insert_file` должна быть последней в строке. * Обратите внимание *, что ни пробел, ни комментарии после него не допускаются. Код был протестирован с использованием GNU `sed` с включенной опцией` --posix`, и он работал как положено, поэтому он должен работать с любым * posix-совместимым * `sed`. Peter.O 10 лет назад 3
Боже мой, это круто! Это происходит в моем словаре sed! Великолепно полезно и красиво просто. Спасибо! DanielSmedegaardBuus 9 лет назад 1
Обратите внимание, что редактирование на месте требует, чтобы вы захватили выходные данные sed (например, `output = $ (sed -e" ... "существующий_файл)`) и затем произвели замену во втором проходе (например, `echo" $ output "> существующий_файл`), поскольку попытка перенаправить в файл, из которого вы читаете, приведет к его усечению до прочтения содержимого. Chris Tonkinson 8 лет назад 2
4
Dr Kitty

Предупреждение: это определенно не самый простой способ сделать это. (РЕДАКТИРОВАТЬ: Bash работает; POSIX grep тоже хорошо)

Если основной текст находится в файле «main», а сгенерированный контент - в файле «gen», вы можете сделать следующее:

#!/bin/bash BEGIN_GEN=$(cat main | grep -n '### BEGIN GENERATED CONTENT' | sed 's/\(.*\):.*/\1/g') END_GEN=$(cat main | grep -n '### END GENERATED CONTENT' | sed 's/\(.*\):.*/\1/g') cat <(head -n $(expr $BEGIN_GEN - 1) main) gen <(tail -n +$(expr $END_GEN + 1) main) >temp mv temp main 
Это работает? Я думаю, что ваша последняя строка откроет `main` для записи, очистки, прежде чем она будет прочитана кошкой. chepner 12 лет назад 0
@chepner Дерьмо, ты прав. Остальное работает, хотя. Я исправлю это. Dr Kitty 12 лет назад 0
4
smokris
newContent=`cat new_file` perl -0777 -i -pe "s/(### BEGIN GENERATED CONTENT\\n).*(\\n### END GENERATED CONTENT)/\$1$newContent\$2/s" existing_file 
Хорошая работа. Гораздо проще, чем у меня. :) Dr Kitty 12 лет назад 0
1
Jetchisel
ed -s FILE1 <<EOF /### BEGIN GENERATED/+,/### END GENERATED/-d /### BEGIN GENERATED/ r FILE2 w q EOF 
Использование heredoc и редактора ed line. Первая строка внутри heredoc должна удалить 'd' строку после '+' '### BEGIN gENERATED ...' и строку перед '-' '### END GENERATED ...' во второй строке вставить FILE2 после строки ### END GENERATED ... ' Jetchisel 10 лет назад 0
извините, я имел в виду вставить FILE2 после строки "### BEGIN GENERATED .." Jetchisel 10 лет назад 0
Полегче на меня, ребята, это ведь мой первый раз :-). Также я мог бы использовать слово то же самое, но другое решение использует не heredocs, а printf и pipe. В любом случае извиняюсь, если я допустил ошибку :-) Jetchisel 10 лет назад 0

Похожие вопросы