URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 8869
[ Назад ]

Исходное сообщение
"Sed question"

Отправлено localhorst , 24-Сен-10 09:58 
Есть файл 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 question"
Отправлено temny , 24-Сен-10 10:59 
У меня получилось вот так:

$ 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 question"
Отправлено Andrey Mitrofanov , 24-Сен-10 13:34 
>У меня получилось вот так:
>
>
$ 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 - к чему бы это? :-/


"Sed question"
Отправлено temny , 24-Сен-10 14:19 
В данный момент не помешало бы уточнение условий задачи. В моём понимании запись start-flag 0-flag 1-end должна быть напечатана, в вашем - нет. И похоже, что ваше решение "сработает" на start-end, без flag-ов внутри.

Но вообще прикольно, короче чем у меня :)


"Sed question"
Отправлено temny , 24-Сен-10 15:17 
Ещё один способ для 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


"Sed question"
Отправлено localhorst , 24-Сен-10 16:34 
>В данный момент не помешало бы уточнение условий задачи. В моём понимании
>запись start-flag 0-flag 1-end должна быть напечатана, в вашем - нет.
>И похоже, что ваше решение "сработает" на start-end, без flag-ов внутри.
>
>
>Но вообще прикольно, короче чем у меня :)

Задача именно печатать start-flag 0-end, только этот блок.
Первый вариант подошел, но пока я не до конца вник в его логику, как вникну - поизучаю остальные.

А вообще где-то написано на толковом языке как мастерить подобные выражения на sed? Рыл маны и гугл - как-то ничего не вышло.


"Sed question"
Отправлено temny , 24-Сен-10 17:12 
>А вообще где-то написано на толковом языке как мастерить подобные выражения на
>sed? Рыл маны и гугл - как-то ничего не вышло.

На ум приходит только "O'reilly - sed and awk Pocket Reference" - просто чуть глубже чем в мане.

И как один из способов которым пользовался я - брал
http://sed.sourceforge.net/sed1line.txt
выбирал пример попроще и перечитывая в мане описание каждой из функций пытался понять "почему/как это работает".