выборочное удаление линий между двумя шаблонами

выборочное удаление линий между двумя шаблонами

У меня есть файл, который содержит следующее содержимое:

Hello world Unix!!
Its bright world
Current time is HH:mm:ss
Next action plan is item #3
End of task.
Thank you.


Hello world Linux!!
All actions completed.
End of Activity.
Thanks.

Я хотел бы выборочно удалить все строки, содержащие ключевое слово «world», а также все последующие строки, пока не встретится строка с определенным набором ключевых слов (например, «Activity» или «task»).

Желаемый результат:

End of task.
Thank you.
End of Activity.
Thanks. 

решение1

Пытаться:

$ awk  -v f=1 '/world/{f=0} /Activity|task/{f=1} f' File
End of task.
Thank you.


End of Activity.
Thanks.

Как это работает:

  1. -v f=1

    Создайте переменную awk fи присвойте ей значение 1.

  2. /world/{f=0}

    Если текущая строка содержит world, установите переменную fв ноль.

  3. /Activity|task/{f=1}

    Если строка содержит Activityили task, то установите fзначение 1.

    Обратите внимание, что worldвыше и Activityили taskздесь рассматриваются как регулярные выражения. Кроме того, они чувствительны к регистру.

  4. f

    Если fненулевое значение, выведите строку.

Чтобы также удалить пустые строки

$ awk  -v f=1 '/world/{f=0} /Activity|task/{f=1} f && /./' File
End of task.
Thank you.
End of Activity.
Thanks.

f && /./сообщает awk, что нужно печатать строку только если fона не равна нулюистрока содержит хотя бы один символ (любого вида).

решение2

Не так красиво, как решение awk, но поскольку автор вопроса пометил вопрос тегомседтоже, вот:

#with blank lines
sed '/world/,/task\|Activity/{//!d};/world/d' file

#without blank lines
sed '/world/,/task\|Activity/{//!d};/world\|^$/d' file

Обратите внимание на использование //, что означает предыдущее использованное регулярное выражение :)

Связанный контент