У меня есть файл, который помимо прочего содержит записи следующей формы:
2012-01-12 22:20:21,638 INFO [Tracer]
something.of.interest
...some number of additional lines...
<<a blank line>>
...other stuff...
Я хочу выделить только те блоки текста, где первая строка содержит [Tracer], а вторая строка содержит нечто.of.интерес , заканчивая пустой строкой неизвестное количество строк после вторая линия. Изменение формата файла не вариант.
Я могу использовать sed, чтобы выделить весь блок, выполнив что-то похожее на:
gsed -n '/^[0-9]\{4\}[^\[]*\[Tracer\]/,/^$/ p' /path/to/file/to/parse
Это выбирает весь блок, как и предполагалось, но совпадает с записями, где вторая строка не содержит что-то интересное.
Я могу использовать N, чтобы получить следующую строку, а затем сопоставить текущую и следующую строки, и я могу сделать эту работу, чтобы выбрать первые две строки, только когда я вижу и [Tracer], и что-то из интереса, разделенного \ п, однако я не могу понять, как захватить следующие строки, пока я не достигну новой строки. В псевдоеде я хочу сделать что-то вроде этого:
/look for Tracer line 1/{
N
/look for \n.*something.of.interest/
},
/look for blank line for end of range/
p
К сожалению, на самом деле это не работает, обычно я получаю сообщение «неизвестная команда».
Есть ли способ определить диапазон в sed, используя шаблоны, где начало и конец могут быть многострочными?
В конечном итоге решение должно работать на Solaris 5.10. GNU sed (gsed) доступен, как и awk, если это лучший выбор в этом случае.
Предложения очень ценятся.
UPDATE
Кажется, я могу сделать это в awk, хотя результат слегка ужасающий. Я бы очень хотел более элегантное решение, но для справки здесь есть скрипт awk, который найдет интересующие вас строки:
1) Создайте файл something.awk, где первая строка - это регулярное выражение для соответствия строке 1:
/\[Tracer\]/ {
l1=$0
if (getline <= 0) {
print "getline failed"
exit 1
}
if (index($0, L2MARKER) > 0) {
print l1
print $0
stop=0
while(stop != 1) {
if (getline <= 0) {
print "getline failed :( ERRNO:" + ERRNO
exit 1
}
print;
if (length($0) == 0) {
stop = 1
}
}
}
}
2) Вызывать из оболочки, аналогичной awk -fthing.awk L2MARKER ='thing.of.интерес 'the.file.to.parse