Как выбрать линии между двумя шаблонами маркеров, которые могут возникать несколько раз с помощью awk/sed
Используя awk
или sed
, как я могу выбрать строки, которые происходят между двумя разными маркерными шаблонами? Может быть несколько разделов, помеченных этими шаблонами.
Например:
Предположим, что файл содержит:
abc
def1
ghi1
jkl1
mno
abc
def2
ghi2
jkl2
mno
pqr
stu
И начальный шаблон abc
, а конечный шаблон - mno
Итак, мне нужен вывод как:
def1
ghi1
jkl1
def2
ghi2
jkl2
Я использую sed для соответствия шаблону один раз:
sed -e '1,/abc/d' -e '/mno/,$d' <FILE>
Есть ли способ в sed
или awk
сделать это несколько раз до конца файла?
Ответы
Ответ 1
Используйте awk
с флагом для запуска печати при необходимости:
$ awk '/abc/{flag=1;next}/mno/{flag=0}flag' file
def1
ghi1
jkl1
def2
ghi2
jkl2
Как это работает?
-
/abc/
соответствует линиям, имеющим этот текст, а также /mno/
.
-
/abc/{flag=1;next}
устанавливает flag
, когда текст abc
найден. Затем он пропускает строку.
-
/mno/{flag=0}
выводит flag
при появлении текста mno
.
- Финал
flag
- это шаблон с действием по умолчанию, который равен print $0
: если flag
равно 1, строка печатается.
Для более подробного описания и примеров, а также случаев, когда шаблоны либо показаны, либо нет, см. Как выбрать строки между двумя шаблонами?.
Ответ 2
Использование sed
:
sed -n -e '/^abc$/,/^mno$/{ /^abc$/d; /^mno$/d; p; }'
Опция -n
означает, что по умолчанию печать не выполняется.
Образец ищет строки, содержащие только abc
, только mno
, а затем выполняет действия в { ... }
. Первое действие удаляет строку abc
; вторая строка mno
; и p
печатает оставшиеся строки. Вы можете расслаблять регулярные выражения по мере необходимости. Любые строки вне диапазона abc
.. mno
просто не печатаются.
Ответ 3
Это может сработать для вас (GNU sed):
sed '/^abc$/,/^mno$/{//!b};d' file
Удалите все строки, кроме строк, начинающихся с abc
и mno
Ответ 4
sed '/^abc$/,/^mno$/!d;//d' file
Гольфы два персонажа лучше, чем ppotong - х {//!b};d
Пустые косые черты //
означают: "повторное использование последнего регулярного выражения". и команда делает то же самое, что и более понятное:
sed '/^abc$/,/^mno$/!d;/^abc$/d;/^mno$/d' file
Кажется, это POSIX:
Если RE пусто (т.е. Не указывается шаблон), sed должен вести себя так, как если бы последний RE использовался в последней применяемой команде (либо в качестве адреса, либо как часть замены).
Ответ 5
Из предыдущих ссылок ответа тот, который сделал это для меня, выполнив ksh на Solaris, был следующим:
sed '1,/firstmatch/d;/secondmatch/,$d'
Ответ 6
Don_crissti ответ от Показывать только текст между двумя шаблонами соответствия?
firstmatch="abc"
secondmatch="cdf"
sed "/$firstmatch/,/$secondmatch/!d;//d" infile
который намного эффективнее, чем приложение AWK, см. здесь.
Ответ 7
что-то вроде этого работает для меня:
file.awk:
BEGIN {
record=0
}
/^abc$/ {
record=1
}
/^mno$/ {
record=0;
print "s="s;
s=""
}
!/^abc|mno$/ {
if (record==1) {
s = s"\n"$0
}
}
используя: awk -f file.awk data
...
edit: решение O_o fedorqui лучше/красивее моего.
Ответ 8
perl -lne 'print if((/abc/../mno/) && !(/abc/||/mno/))' your_file