grep with streaming data

Gunsleader

под streaming data я понимаю парсер который за один проход(One-pass) поток большой - обратный проход неприемлем)
Как заставить grep(или какие аналоги посоветуете вроде греп one-pass? ) работать с потоком в котором могут встретиться символы \n etc
in.txt
WARNING: 123 \n
NOTE: 123
grep ^WARNING:.*NOTE: in.txt >res.txt
не находит ничего(т.к. смотрит построчно)

pitrik2

что делать в таком случае
in.txt
WARNING:
....
тут очень очень длинный файл
....
последняя строчка: NOTE
как такой файл грепать? полностью загружать его в память и потом полностью его вываливать в ответ?

pitrik2

это я к тому что полностью ко всему потоку применять рег. выражение бессмысленно
скорей нада уметь искать в нескольких соседних строчках
а эта задача уже легко решается
например с помощью sed

tokuchu

работать с потоком в котором могут встретиться символы \n etc
Это перевод строки что ли?
grep работает с потоком нормально, обрабатывает построчно.
Т.е. на несколько строк не будет матчиться. Это можно изменить, кажется, но по умолчанию так. Кроме того, если надо на несколько строк матчить, то с жадными регулярными выражениями могут проблемы быть.

klyv

как такой файл грепать? полностью загружать его в память и потом полностью его вываливать в ответ?
а как он грепает очень длинные строчки?

Gunsleader

Да именно так и надо вывалить весь кусок в ответ, по структуре файла знаю что этот варнинг займет примерно 3-4 строки, как сделать с помощью sed'a не совсем понимаю, вроде греп лимитирован длинной строки( 4096 та версия что нашел под винду)
Я просто sed плохо знаю. Читаю пока мануалы, но если ктото уже напишет пример скрипта буду очень признателен.

pitrik2

как сделать с помощью sed'a не совсем понимаю
ну поищи примеры в гугле
или ман почитай
смысл там типа такого:
смотрим строчку, если буфер пустой и строчка содержит начало поиска, то добавляем строчку в буфер
если буфер пустой и строчка не содержит начало поиска - игнорируем ее
если буфер не пустой и строчка содержит конец поиска - выплевываем рузельтат, очищаем буфер
если буфер не пустой и строчка не содержит конец поиска - добавляем ее в буфер

tokuchu

Да именно так и надо вывалить весь кусок в ответ, по структуре файла знаю что этот варнинг займет примерно 3-4 строки
Ты неправильно понял. Если будет 10 таких варнингов, то тебе вывалится всё начиная от начала первого и заканчивая последней строчкой последнего. Причём и то, что посередине - тоже.
Вообще, grep выводит не то, что он поматчил, а ту строчку, в которой он это поматчил.
Такое поведение, какое тебе надо, можно достаточно просто сделать с помощью sed или awk.

klyv

а как он грепает очень длинные строчки?
и всё же?

tokuchu

и всё же?
Учитывая, что ему строчку нужно всю помнить, т.к. заранее не известно о том, поматчится она или нет, то он её в память загружает.
А вообще в теории матчить можно и так, что каждый просмотренный байт можно забывать. Но если выводить надо, то придётся запоминать.

hwh2010

смотрим строчку, если буфер пустой и строчка содержит начало поиска, то добавляем строчку в буфересли буфер пустой и строчка не содержит начало поиска - игнорируем ееесли буфер не пустой и строчка содержит конец поиска - выплевываем рузельтат, очищаем буфересли буфер не пустой и строчка не содержит конец поиска - добавляем ее в буфер
эт какой-то изврат. Неужели нет подобного струмента, который рассматривает перенос строки как обычный символ?

pitrik2

эт какой-то изврат. Неужели нет подобного струмента, который рассматривает перенос строки как обычный символ?
ну как бы можно это запрограммить например на перле
стандартных консольных утилит не знаю :(

klyv

Неужели нет подобного струмента, который рассматривает перенос строки как обычный символ?
можешь в этом потоке заменить все переводы строк на что-нить особенное и искать в этом грепом.

pitrik2

можешь в этом потоке заменить все переводы строк на что-нить особенное и искать в этом грепом.
tr кстати с этим отлично справляется
| tr "\n" "@"

klyv

по-хорошему, сперва заменить переводы строк на собачек, а собачек задвоить, потом обработать, потом сдвоенных собачек сделать одиночными, а несдвоенных - переводами строк :)

Gunsleader

Написал на sed'e, тему можно закрывать. всем спасибо за ответы.

klyv

Написал на sed'e, тему можно закрывать. всем спасибо за ответы.
ну покажи красоту :)

tokuchu

эт какой-то изврат. Неужели нет подобного струмента, который рассматривает перенос строки как обычный символ?
Никакого изврата. Инструмены есть. И тот же grep это умеет, в том числе выводить только поматченный образец. Я уже писал об этом. И о проблемах такого решения тоже.

Gunsleader

Извините за кривой код...
all.sh:
#!/usr/bin/bash
base="$@"
echo $base
cat $base | sed -f 2.scr | sed -f 3.scr | sed -f 4.scr > res.txt
2.scr:
# preprocess file...
/^ *$/d
/ The SAS System *.*2008/d
#kill header
1,/NOTE:/{
/NOTE:/!d
}
#kill all notes
/NOTE:/,/WARNING:/{
/WARNING:/!d
}
#kill tail
/NOTE:/,${
d
}
s/WARNING/\
WARNING/g
3.scr:
/^$/b
:loop
$!{
N
/\n$/!b loop
}
s/\n\(.\)/\1/g
4.scr:
/^$/d
Почему то все вместе в одном файле работает неверно, не стал разбираться ибо был ограничен во времени решения задачи, просто разбил на независимые файлы.

pitrik2

почему всё не отформатировано? читать же невозможно
s/WARNING/\
WARNING/g
что это?
*.*
что это?
Оставить комментарий
Имя или ник:
Комментарий: