Есть файл tst.sed:
-----------
line0
line1
line2
line3
line4
START
line5
line6
line7
FLAG 0
line8
line9
END
line10
line11
line12
line13
line14
line15
line16
line17
line18
line19
START
line20
line21
line22
line23
FLAG 1
line24
line25
line26
line27
END
line28
line29
line30
-----------Хочу выцепить из него блог START-FLAG 0-END и ничего больше, затык сразу:
-----------
[insane@my ~/test]$ sed -n '/^START$/,/^FLAG 0$/p' tst.sed
START
line5
line6
line7
FLAG 0
START
line20
line21
...
и далее до конца файла
-----------В мане про -n:
-n By default, each line of input is echoed to the standard output
after all of the commands have been applied to it. The -n option
suppresses this behavior.Логика вроде бы правильная, но не работает.
FreeBSD 6.4-RELEASE-p7
У меня получилось вот так:
$ sed -nE '/^START$/h;/^END$/{x;/^START.*\nFLAG 0(\n|$)/{p;x;p;x;};};/^START$/!{x;/^START/!x;/^START/{x;H;};};' tst.sed
START
line5
line6
line7
FLAG 0
line8
line9
ENDЛогика следующая:
Если текущая строка START - сохраняем её в hold space (сбрасывая прежнее содержимое);
Если текущая строка END - проверяем, если в hold space присутствует и START и FLAG 0, то печатаем hold space, печатаем текущую строку и "сбрасываем" hold space (для того чтоб не попасться на START-FLAG 0-END-END)
Eсли текущая строка не STARТ и в hold space уже пристутствует START, то дописываем текущую строку к hold spaceСпособ который пытались использовать вы не работал по той причине, что sed "смотрит" на подобные записи следующим образом:
текущая строка соответствует address #1 (т.е. /^START$/)? - если да, то выполняем указанную последовательность (т.е. "p") для текущей строки и всех следующий, пока не встретими address #2 (т.е. /^FLAG 0$/), либо до конца входного потока. Т.е. sed обрабатывает входной поток построчно.
>У меня получилось вот так:
>
>$ sed -nE '/^START$/h;/^END$/{x;/^START.*\nFLAG 0(\n|$)/{p;x;p;x;};};/^START$/!{x;/^START/!x;/^START/{x;H;};};' tst.sedА у меня вот так -
sed -n '/^START$/{h;d};x;/./!{x;d};x;H;/^flag 0$/!{/^flag /bc};/^END$/!d;x;/./p;:c;s/.*//;h'>Логика следующая:
Накапливаем "правильние" строки в hold-е следующим образом:
Если строка =="START" - "просто" поместить её в буфер = начать накопление [заново].
(до [первого] START буфер пустой, если "вдруг" START повторился - сбрасываем, чтоб не было вложений)
Если буфер пуст (не накапливаем строки, вне блока START-END), читать следующую строку == отбросить тек строку.
[Буфер не пуст,в буфере уже есть START] -- добавить тек.строку к нему.Если строка - flag, но не "flag 0", то сбросить буфер [- не накапливать больше].
Если "END", напечатать накопленное, если там что-то было, и очистить буфер. (буфер пустой = ждём слкдующего START)
PS: Какой выразительный язык!(тм) Я начинаю догадываться, почему не люблю perl... Ж))))
PPS: ...постоянно путаю n вместо d - к чему бы это? :-/
В данный момент не помешало бы уточнение условий задачи. В моём понимании запись start-flag 0-flag 1-end должна быть напечатана, в вашем - нет. И похоже, что ваше решение "сработает" на start-end, без flag-ов внутри.Но вообще прикольно, короче чем у меня :)
Ещё один способ для gnu-sed пришел в голову:$ gsed -nE ':a;N;/\nSTART$/{s!.*\n!!};/^START.*\nFLAG 0\n(|.*\n)END$/{p;b};ba' tst.sed
START
line5
line6
line7
FLAG 0
line8
line9
END
>В данный момент не помешало бы уточнение условий задачи. В моём понимании
>запись start-flag 0-flag 1-end должна быть напечатана, в вашем - нет.
>И похоже, что ваше решение "сработает" на start-end, без flag-ов внутри.
>
>
>Но вообще прикольно, короче чем у меня :)Задача именно печатать start-flag 0-end, только этот блок.
Первый вариант подошел, но пока я не до конца вник в его логику, как вникну - поизучаю остальные.А вообще где-то написано на толковом языке как мастерить подобные выражения на sed? Рыл маны и гугл - как-то ничего не вышло.
>А вообще где-то написано на толковом языке как мастерить подобные выражения на
>sed? Рыл маны и гугл - как-то ничего не вышло.На ум приходит только "O'reilly - sed and awk Pocket Reference" - просто чуть глубже чем в мане.
И как один из способов которым пользовался я - брал
http://sed.sourceforge.net/sed1line.txt
выбирал пример попроще и перечитывая в мане описание каждой из функций пытался понять "почему/как это работает".