У меня есть файл, который содержит следующее содержимое:
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.
Как это работает:
-v f=1
Создайте переменную awk
f
и присвойте ей значение1
./world/{f=0}
Если текущая строка содержит
world
, установите переменнуюf
в ноль./Activity|task/{f=1}
Если строка содержит
Activity
илиtask
, то установитеf
значение1
.Обратите внимание, что
world
выше иActivity
илиtask
здесь рассматриваются как регулярные выражения. Кроме того, они чувствительны к регистру.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
Обратите внимание на использование //
, что означает предыдущее использованное регулярное выражение :)