Как я могу использовать sed или ex для замены блока (многострочный код) новым блоком текста (кода)?

Я должен заменить большой блок текста (код сценария оболочки) в файле с другим блоком текста.

Я впечатлен тем, как использовать sed для замены многострочной строки? ответил антак и многострочная замена, на которые ответил Брюс Эдигер

Но у меня есть некоторые проблемы с их использованием.

  1. Антак уже упоминал в своем ответе, что потоковый файл целиком ( 1h;2,$H;$!d;g; ) в буфер не рекомендуется для больших файлов, поскольку он перегружает память.

  2. Я знаю, что sed можно использовать с функцией блока, чтобы сохранить текст вне блока без изменений. Я хочу использовать эту функцию. Но если я использую,

     sed -i '/marker1/,/marker2/s/.*/new text (code)/' filename 

он будет вставлять новый текст (код) несколько раз для каждого потока. Следовательно, я должен сделать визуальный блок одним потоком, используя что-то похожее на то, что было предложено antak раньше, но для блока (а не для всего файла).

  1. Как упоминалось Брюсом Эдигером, добавьте функцию ex которая начинается с конца . (точка) можно попробовать, но мой новый текст (код) содержит строки, начинающиеся с точки, которые можно рассматривать как точку синтаксиса append. Как я могу использовать его в этой ситуации?

  2. ex 's dd ' количество строк 'может удалять несколько строк, но если у меня есть блок между / marker1 / и / marker2 / с числом строк, не фиксированным (изменяющимся), следует заменить новым текстом (кодом), как сделать это ?

  • Группировка строк в гетерогенные подмножества
  • Удаление непечатаемых символов с помощью POSIX sed
  • Печать строк между двумя шаблонами с SED
  • Как извлечь строку из файла в определенном состоянии
  • Разбор допустимого вывода в скрипте оболочки с помощью sed / grep
  • Как удалить теги html из файла с помощью sed?
  • Unix ищет и удаляет переменную (содержит косую черту) из файла
  • Строки - Извлечь версию файла Рекурсивный
  • 3 Solutions collect form web for “Как я могу использовать sed или ex для замены блока (многострочный код) новым блоком текста (кода)?”

    Использование GNU sed

    Для замены строк, начинающихся с строки, соответствующей 3 и продолжения строки, соответствующей 5 с помощью New Code :

     $ seq 8 | sed '/3/,/5/{/5/ s/.*/New Code/; t; d}' 1 2 New Code 6 7 8 

    Для строк в диапазоне /3/,/5/ мы проверяем, соответствует ли строка 5 (что означает, что это последняя строка в группе), и если да, то мы делаем замену, чтобы вставить New Code . Если подстановка была сделана, команда t подскажет sed перейти к концу команд (в этом случае будет напечатан New Code ). Если нет, команда d сообщает sed удалить строку.

    Все остальные строки печатаются нормально.

    Чтобы изменить файл на месте, можно использовать опцию -i :

     sed -i.bak '/3/,/5/{/5/ s/.*/New Code/; t; d}' file 

    Использование awk

    Чтобы сделать то же самое с помощью awk:

     $ seq 8 | awk '/3/,/5/{if (!f)print "New Code"; f=1; next}; 1' 1 2 New Code 6 7 8 

    Команда awk обрабатывает строки в диапазоне /3/,/5/ специально. Для строк в этом диапазоне мы проверяем, является ли f нулевым (то есть if !f истинно), и если это так, мы печатаем New Code и устанавливаем f в 1, а затем пропускаем остальные команды и переходим к next строка.

    Для линий вне диапазона /3/,/5/ переход не выполняется, а 1 вызывает печать строки. Более подробно, 1 является условием. Поскольку 1 не равно нулю, условие принимает значение true. Поскольку никакое действие не связано с условием, выполняется действие по умолчанию, которое должно печатать строку. Таким образом, 1 является сокращением для печати.

    Чтобы изменить файл на месте, можно использовать опцию -i inplace с GNU awk 4.1 или выше:

     awk -i inplace '/3/,/5/{if (!f)print "New Code"; f=1; next} 1' file 

    Я предлагаю использовать команду c hange (которая по существу является d elete в сочетании с ppend, хотя append применяется только для последней строки в диапазоне, который именно вы здесь хотите):

     sed -i '/marker1/,/marker2/c\ New text 1\ New text 2' filename 

    Здесь используется синтаксис GNU sed для редактирования на месте ( -i ). Эта команда c в противном случае является стандартной и переносной. sed GNU sed :

     sed '/marker1/,/marker2/cNew text 1\ New text 2' filename 

    как нестандартное расширение.

    Символы новой строки и обратной косой черты должны быть экранированы (с обратной косой чертой) в заменяемом тексте.

    Основываясь на приведенном выше обсуждении, я придумываю решение, используя ex

     seq 15 > test1.txt ex test1.txt << EOEX /^7/,/^9/c abcd 123 .xyz hfr4 . w! q EOEX cat test1.txt 

    Вышеприведенное дает

     1 2 3 4 5 6 abcd 123 .xyz hfr4 10 11 12 13 14 15 

    Спасибо g-man, чтобы сообщить мне об изменении команды и дать разъяснения о точке. Оба sed и ex используют почти аналогичный синтаксис команды change (также для команды delete, команды append и т. Д.).

    Linux и Unix - лучшая ОС в мире.