Как выбрать линии между двумя шаблонами маркеров, которые могут возникать несколько раз с 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
делать это повторно до конца файла?
8 ответов:
использовать
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
- это шаблон с действием по умолчанию, которая заключается вflag
равно 1 строка печатается.для более подробного описания и примеров, а также случаев, когда шаблоны либо показаны, либо нет, см. Как выбрать между двух моделей?.
используя
sed
:sed -n -e '/^abc$/,/^mno$/{ /^abc$/d; /^mno$/d; p; }'
The
-n
опции не печатать по умолчанию.шаблон ищет строки, содержащие только
abc
простоmno
, а затем выполняет действия в{ ... }
. Первое действие удаляетabc
строка; второй -mno
линия,p
печать оставшихся строк. Вы можете расслабить регулярные выражения по мере необходимости. Любые линии вне диапазонаabc
..mno
просто не печатается.
Это может сработать для вас (GNU sed):
sed '/^abc$/,/^mno$/{//!b};d' file
удалить все строки, кроме тех, между строками, начиная
abc
иmno
sed '/^abc$/,/^mno$/!d;//d' file
гольфы два символа лучше, чем ppotong это
{//!b};d
пустые косые черты
//
mean:"повторно использовать последнее регулярное выражение, используемое". и команда делает то же самое, что и более понятно:sed '/^abc$/,/^mno$/!d;/^abc$/d;/^mno$/d' file
этой кажется, POSIX:
если RE пуст (то есть не указан шаблон) sed должен вести себя так, как если бы последний RE использовался в последней примененной команде (либо как адрес, либо как часть заменяющей команды) был указан.
из ссылок предыдущего ответа, тот, который сделал это для меня, запустив ksh на Solaris, был следующим:
sed '1,/firstmatch/d;/secondmatch/,$d'
ответ Don_cristi от показать только текст между 2 шаблон?
firstmatch="abc" secondmatch="cdf" sed "/$firstmatch/,/$secondmatch/!d;//d" infile
что намного эффективнее, чем приложение AWK, см. здесь.