Как извлечь строку между двумя шаблонами с помощью sed в Linux, а второй шаблон повторяет больше строк в файле

Например

xyz A1 B1 C1 D1 End End End X1 X2 X3 Done 

Я хочу извлечь всю строку между xyz и End pattern. Поэтому вывод должен быть

 xyz A1 B1 C1 D1 End End End 

  • Как выполнить операцию по отдельным матчам в полной строке
  • дифференцируя два файла и получая уникальный результат в третьем
  • Как свернуть 'grep -c <токен> * .h * .cpp' в один счет?
  • Как удалить все числа, окруженные <>
  • Сбросьте шаблон слова в конце строки, используя sed
  • Извлечение IP-адреса из текста и сохранение его в переменной
  • Помощь с повторением поля A в CSV-файле, где поле B имеет указанное значение
  • wget on Centos 7 Terminal как загрузить только текст без кода стиля сайта
  • 5 Solutions collect form web for “Как извлечь строку между двумя шаблонами с помощью sed в Linux, а второй шаблон повторяет больше строк в файле”

    Это своего рода работа pcregrep :

     pcregrep -M 'xyz(.|\n)*End' file 

    Заметьте, что он очень жадный и ест все до финала, включая другие End .

    Perl для спасения: напечатайте все строки между первым xyz и последним End :

      perl -ne ' $inside = 1 if /^xyz$/; $seen_end = 1 if $inside && /^End$/; push @buff, $_ if $inside; print splice @buff if /^End$/ && @buff; ' input-file 

    Из первого появления xyz мы начинаем толкать все строки в буфер. После того, как End встречается, мы выводим и очищаем буфер (см. Сращивание ), но мы продолжаем нажимать строки в буфер в случае, если был еще один End позже.

    Поскольку вы запрашиваете решение sed , я бы сделал это следующим образом:

     sed -e '/^xyz$/!d;:a' -e '$!{N;ba' -e '};s/\(.*\nEnd\).*/\1/' 

    Поэтому отбросьте все до первого шаблона ( /^xyz$/!d ), затем зациклируйте, чтобы собрать все оставшиеся строки в пространстве шаблонов ( :a;$!{N;ba ) и удалить все за последним вхождения второго шаблона ( s/\(.*\nEnd\).*/\1/ ).

    Сбор в пространстве шаблонов необходим, поскольку адресация ( /xyz/,/End/ ) не является жадным, но .* Внутри пространства шаблонов.

    Решение awk :

     awk '/xyz/,/End/{ print $0; n=NR }($0=="End" && n && NR>n && NR-n++ == 1)' file 

    Выход:

     xyz A1 B1 C1 D1 End End End 

    • /xyz/,/End/ – диапазон записи, от xyz до End

    • n=NR – фиксирующий номер записи (при согласовании диапазона – в конечном итоге будет содержать номер последней записи диапазона)

    Метод-а

     perl -l -0777ne 'print /^(xyz.*?^End$(?:\nEnd$)*)/ms' yourfile 

    За работой

    • Перетащите файл так, чтобы он отображался как строка looooong, которую затем можно разделить с помощью соответствующего регулярного выражения. Регулярное выражение в этом случае:
      • ищите xyz в начале строки (не обязательно файл).
      • найдите ближайший конец в строке, а затем столько же последовательных строк.

    Метод-2

     perl -lne ' next unless /xyz/ ... eof; last if !/End/ and $flag; $flag ||= 1 if /End/; print; ' yourfile 

    За работой

    • Здесь мы используем Perl на основе строки и настраиваем небольшой конечный автомат.
      • Отклонить любую недиапазонную часть файла.
      • Когда мы входим в правильный диапазон, мы печатаем все строки, пока не нажмем на / End / line. В этот момент мы устанавливаем флаг.
      • Затем мы выходим, как только видим первую строку non / End /.

    Метод-3

     sed -e ' /xyz/!d :a $q;N /\nEnd$/!ba :b n /End/bb d ' yourfile 

    В этом методе мы используем первый цикл do-while (: a), который будет накапливать строки, начинающиеся с / xyz / to / End /.

    Второй цикл do-while (: b) будет печатать строки до следующей строки / End /.

    Метод-4

     sed -e ' /xyz/,/End/!d H;/xyz/h;/End/!d :a $q;N /\(.*\)\n\1$/!{g;q;} s/.*\n//;H ba ' yourfile 

    С помощью этого метода мы сначала выбираем правильный диапазон, а затем сохраняем данные диапазона в пространстве удержания. Цикл do-while (: a) – это настройка, которая постепенно добавляется в пространство удержания, в то время как следующая строка имеет значение / End /.

    Результаты

     xyz A1 B1 C1 D1 End End End 
    Linux и Unix - лучшая ОС в мире.