Удалить неизвестное количество строк, кроме последней строки

Блок всегда начинается с: 00 ПРОГРАММА

и заканчивается XYZ, за которым следует пустая строка. XYZ также появляется раньше, в блоке строк, но за более ранними строками следуют больше данных. Мне просто нужна последняя строка перед пустой строкой. Я не нашел кода, который, похоже, соответствует моим намерениям. Надеюсь, это будет легкий ответ для кого-то!

Я хочу сохранить последнюю строку перед пустой строкой. Например:

000-12-22

AB1

00 ПРОГРАММА

01 ЗАПРОС

03 XYZ

04 XYZ

пустая строка

LINE VALUE

00456

Только эту часть следует удалить.

00 ПРОГРАММА

01 ЗАПРОС

03 XYZ

FYI … Дон, я обещаю прочитать инструкции по отправке по следующему вопросу! 🙂

Ответ на пересмотренный вопрос

Рассмотрим этот тестовый файл;

$ cat File2 000-12-22 AB1 00 PROGRAM 01 INQUIRY 03 XYZ 04 XYZ LINE VALUE 00456 

Попробуйте эту команду:

 $ sed '/00 PROGRAM/,/^$/{/./{h;d}; x; p; x;}' File2 000-12-22 AB1 04 XYZ LINE VA 

LUE 00456

Ответ на оригинальный вопрос

Если я правильно понял, у вас есть файл, содержащий группы залогов, которые начинаются с строки, содержащей 00 PROGRAM и заканчиваются пустой строкой, и вы хотите, чтобы строка перед пустой строкой содержала XYZ . Если это так, попробуйте следующее:

 sed -n '/00 PROGRAM/,/^$/{/./{h;d}; x;/XYZ/p}' file 

пример

Рассмотрим этот образец файла:

 $ cat file 00 PROGRAM some XYZ discard this data XYZ keep this other 00 PROGRAM more XYZ keep this also end 

Это удерживает только строки XYZ которые предшествуют пустой строке в блоке 00 PROGRAM :

 $ sed -n '/00 PROGRAM/,/^$/{/./{h;d}; x;/XYZ/p}' file XYZ keep this XYZ keep this also 

альтернатива

Возможно, вы хотите сохранить все строки вне группы, а также сохранить последнюю непустую строку группы, если она соответствует XYZ . В таком случае:

 $ sed '/00 PROGRAM/,/^$/{/./{h;d}; x;/XYZ/!d}' file XYZ keep this other XYZ keep this also end 

Этот тип диапазона является идеальным вариантом использования для ex . Я писал о нем довольно много на этом сайте; это простой инструмент POSIX для редактирования сценариев.

Команда:

Если вам нужен только один блок, используйте:

 printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x | ex file.txt 

Если есть потенциально несколько блоков, используйте:

 printf '%s\n' 'g/00 PROGRAM/.,/^$/-2d' x | ex file.txt 

Для тестирования используйте %p вместо x :

 printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' %p | ex file.txt printf '%s\n' 'g/00 PROGRAM/.,/^$/-2d' %p | ex file.txt 

Это будет печатать весь буфер, а не сохранять содержимое буфера обратно в файл.


Иллюстрация:

 [vagrant@localhost ~]$ cat file.txt 000-12-22 AB1 00 PROGRAM 01 INQUIRY 03 XYZ 04 XYZ LINE VALUE 00456 [vagrant@localhost ~]$ printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x | ex file.txt [vagrant@localhost ~]$ cat file.txt 000-12-22 AB1 04 XYZ LINE VALUE 00456 [vagrant@localhost ~]$ 

Объяснение и комментарии:

Вы можете использовать ex -c 'editingcommands' filename но я обнаружил, что создает больше проблем, чем он решает. Если ошибка встречается, ex не будет закрываться, но будет зависать в ожидании ввода пользователя. Кроме того, существуют потенциальные проблемы с переносимостью с передачей нескольких команд таким образом, поскольку общие функции, которые позволяют вам это делать, не гарантируются POSIX.

Вместо этого я обычно передаю команды ex из printf . Это позволяет легко разделить несколько строк несколькими командами, используя %s\n в качестве строки формата для printf , и оставляет файл неизменным, если есть ошибка, без зависания (например, если вы попытаетесь отредактировать строку, большую, чем последняя строка файла).

Чтобы проверить команду перед фактическим редактированием файла, я использую %p (print whole buffer) в качестве последней команды. Затем я могу немного подправить команду и запустить ее снова и снова, пока не получу точное содержимое файла, которое я хочу. Как только я доволен результатом, я меняю %p на x и запускаю команду еще раз, чтобы фактически сохранить изменения в файле.

Здесь опять-таки команда, которую я дал в ответ на этот вопрос:

 printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x | ex file.txt 

Команда printf просто печатает три строки /00 PROGRAM/ , .,/^$/-2d и x разделенные символами новой строки, например:

 [vagrant@localhost ~]$ printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x /00 PROGRAM/ .,/^$/-2d x [vagrant@localhost ~]$ 

Эти три строки являются командами ex .

Обзор команд ex

Команда ex имеет две части: адрес (строка) и команду.

Если есть только адрес, курсор переместится на этот адрес (перейдите к этой строке).

Если есть только команда, в качестве адреса используется текущая строка.

Адресом часто может быть диапазон -an-адрес, за которым следует запятая, а затем другой адрес. Это относится ко всем строкам от первого адреса ко второму адресу.

Адрес может быть номером строки, но это необязательно. Это также может быть значением шаблона поиска: «Следующая строка после текущей строки, которая соответствует этому регулярному выражению». Вы можете выполнять поиск в обратном направлении, а также осуществлять прямой поиск.

Вы даже можете написать адрес, который означает: «Две строки перед экземпляром foo который происходит вскоре после экземпляра bar который наиболее непосредственно предшествует текущей строке». Это будет выглядеть так ?bar?/foo/-2

Шаг за шагом

Команда /00 PROGRAM/ – это просто адрес, поэтому это означает «переместить курсор в первый экземпляр шаблона '00 PROGRAM». »

Команда .,/^$/-2d имеет две части. d в конце – это команда, означающая «delete». Остальное – адрес.

Начальный . это специальный адрес, который относится к текущей строке.

Шаблон /^$/ является регулярным выражением для пустой строки (начало строки ^ сразу же после конца строки $ ). В этом случае это означает следующую пустую строку после текущей позиции курсора.

« -2 означает «две линии назад».

Все вместе, то, .,/^$/-2d означает: «Удалите строки из текущей строки в строку две строки над следующей пустой строкой».

x просто означает, сохранить содержимое буфера в файл и выйти из редактора.


Надеюсь, вы сочтете это полезным. ex – чрезвычайно мощный инструмент для редактирования текста. Это непосредственный предшественник vi , который является «визуальным редактором». Все команды ex могут также выполняться в vi .