Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Тексты > Потоковая обработка текста


Автор: Kolgarn 22.4.2012, 07:26
Собственно столкнулся с проблемой.
Пишу небольшой скриптик под одно приложение. Вопрос в том, что актуальность в скрипте должна быть 50-60 мс.

Файл целиком состоит из таких строк:
Код

[07:07:59.503] [SomeBody:123] [Something {3213}] [Here you are (oO)] [oO Kill]

Причем наличие внутренних скобок, двоеточий не постоянно. Что вынудило меня использовать регулярки.

Далее я написал что-то вроде:
Код

$handle = fopen($file,'r');
do
        {
        unset($data,$string);
        $string = trim(stream_get_line($handle, 4096,"\n"));
        if($string) $data = ParsString($string);
        if(!empty($data)) { /* Выводим текст */ }
        if(!$string) usleep($config['timeout']);
        }
while(true);


Нет, оно не падает и прекрасно работает. Вопрос лишь в том, что я совсем не уверен в том, что это такая офигительная идея сидеть на хендале и вот так читать строки.
Уже пару раз оно тупо строки пропускало в рамках тестирования под нагрузкой(пропихивал под парсинг большой поток строк).

Собственно 2 вопроса:
1) Может есть какой-то оригинальный способ разобрать строку не регулярками или с ними но быстрее? При учете, что explode не катит ибо скобки бывают и круглыми и квадратными и треугольными(да и кол-во внутренних переменных не постоянно) -_-
2) Как лучше организовать потоковое чтение из файла? Повторяю актуальность нужна в пределах 50 мс, а лучше меньше. 

Автор: Kolgarn 22.4.2012, 09:05
Дополнение по прегам...

Примерно такой хочу использовать что-бы отлавливать все скобки и етк.
Код

$pattern = '#[\(\<\[]{1}([^\{^\]]{1,100})[\s]?([\{\}0-9]{0,100})[\s:]?([^\{^\]]{1,100})[\s]?([\{\}0-9]{0,100})[\]\)\>]{1}#i';


Возникла сложность при анализе текста вроде:
Код

$string = '[07:05:46.809] [Hamster:Die {12345}] [Kill {555}: No {666}]';


Результат:
Код

array (
  0 => 
  array (
    0 => '[07:05:46.809]',
    1 => '07:05:46.80',
    2 => '',
    3 => '9',
    4 => '',
  ),
  1 => 
  array (
    0 => '[Hamster:Die {12345}]',
    1 => 'Hamster:Die ',
    2 => '{12345',
    3 => '}',
    4 => '',
  ),
  2 => 
  array (
    0 => '[Kill {555}: No {666}]',
    1 => 'Kill ',
    2 => '{555}',
    3 => ' No ',
    4 => '{666}',
  ),


Это preg_match_all с PREG_SET_ORDER.

Я вижу где ошибка, но понять не могу как исправить правильнее ее. Не подскажите?
Так же если сможете то, что в {} получать без онных, то цены вообще вам не будет =)

Автор: Kolgarn 22.4.2012, 10:44
Такс... для обработки строк вида:
Код

$string = '[555] [666 {777}] [111:222] [555 {666}: 777 {888}] [999: 000 {111}]';

написал:
Код

$start = '(?:[\[\(\<]{1})';
$end = '(?:[\]\)\>]{1})';
$word = '(?:([^\]^\>^\^)^\{:]{1,100})|([^\]^\>^\^)^\{:]{1,100})[\s]{1}[\{]{1}([0-9]{1,100})[\}]{1})';
$main = '(?:'.$word.'|(?:'.$word.'[:]{1}'.$word.'))';

$pattern = '#'.$start.$main.$end.'#i';


При работе с строкой(preg_match_all + PREG_SET_ORDER) выдает:
Код

array (
  0 => 
  array (
    0 => '[555]',
    1 => '555',
  ),
  1 => 
  array (
    0 => '[666 {777}]',
    1 => '',
    2 => '666',
    3 => '777',
  ),
  2 => 
  array (
    0 => '[111:222]',
    1 => '',
    2 => '',
    3 => '',
    4 => '111',
    5 => '',
    6 => '',
    7 => '222',
  ),
  3 => 
  array (
    0 => '[555 {666}: 777 {888}]',
    1 => '',
    2 => '',
    3 => '',
    4 => '',
    5 => '555',
    6 => '666',
    7 => '',
    8 => ' 777',
    9 => '888',
  ),
  4 => 
  array (
    0 => '[999: 000 {111}]',
    1 => '',
    2 => '',
    3 => '',
    4 => '999',
    5 => '',
    6 => '',
    7 => '',
    8 => ' 000',
    9 => '111',
  ),
)

Что затрудняет анализ. В принципе попробую функцию "маску" написать, которая будет оценивать сопоставление.

Не до конца уверен в правильности абсолютной, посему прошу оценить и подсказать если возможно лучше сделать.

Автор: Kolgarn 23.4.2012, 05:36
Начинаю все больше убеждаться, что php вообще не подходит для подобного... ни одного вразумительного ответа на 4 форумах по этому поводу -_-
Плюс заметил, что так или иначе теряются строки при моей реализации, что не есть хорошо. Может все-таки кто-то сталкивался с анализом текстового файла в потоковом режиме на php?

Автор: ksnk 23.4.2012, 06:06
Цитата(Kolgarn @  23.4.2012,  05:36 Найти цитируемый пост)
ни одного вразумительного ответа на 4 форумах по этому поводу -_-

Обычно, такой результат больше характеризует не о задачу, а того, кто задает вопрос.

Цитата(Kolgarn @  22.4.2012,  07:26 Найти цитируемый пост)
Пишу небольшой скриптик под одно приложение.

Что за приложение? Откуда у приложения взялся php?

Цитата(Kolgarn @  22.4.2012,  07:26 Найти цитируемый пост)
Вопрос в том, что актуальность в скрипте должна быть 50-60 мс.

Смысл этого предложения ускользает.

Цитата(Kolgarn @  22.4.2012,  07:26 Найти цитируемый пост)
1) Может есть какой-то оригинальный способ разобрать строку не регулярками или с ними но быстрее? 

Какие строки? Примеры строк, какой результат нужен? Что значит - разобрать?

Цитата(Kolgarn @  22.4.2012,  07:26 Найти цитируемый пост)
2) Как лучше организовать потоковое чтение из файла? Повторяю актуальность нужна в пределах 50 мс, а лучше меньше. 

Что такое потоковое чтение? Накой оно нужно?

p.s.
«Если вы не можете объяснить что-то шестилетнему ребенку, значит, вы сами этого не понимаете.»
— Энштейн

Автор: Kolgarn 23.4.2012, 06:22
Цитата(ksnk @ 23.4.2012,  06:06)
Цитата(Kolgarn @  23.4.2012,  05:36 Найти цитируемый пост)
ни одного вразумительного ответа на 4 форумах по этому поводу -_-

Обычно, такой результат больше характеризует не о задачу, а того, кто задает вопрос.

Цитата(Kolgarn @  22.4.2012,  07:26 Найти цитируемый пост)
Пишу небольшой скриптик под одно приложение.

Что за приложение? Откуда у приложения взялся php?

Цитата(Kolgarn @  22.4.2012,  07:26 Найти цитируемый пост)
Вопрос в том, что актуальность в скрипте должна быть 50-60 мс.

Смысл этого предложения ускользает.

Цитата(Kolgarn @  22.4.2012,  07:26 Найти цитируемый пост)
1) Может есть какой-то оригинальный способ разобрать строку не регулярками или с ними но быстрее? 

Какие строки? Примеры строк, какой результат нужен? Что значит - разобрать?

Цитата(Kolgarn @  22.4.2012,  07:26 Найти цитируемый пост)
2) Как лучше организовать потоковое чтение из файла? Повторяю актуальность нужна в пределах 50 мс, а лучше меньше. 

Что такое потоковое чтение? Накой оно нужно?

p.s.
«Если вы не можете объяснить что-то шестилетнему ребенку, значит, вы сами этого не понимаете.»
— Энштейн


Мне ваш сарказм не понятен - абсолютно все было уже сказано в теме из вами перечисленного.
По пунктам, пропуская первое высказывание:
1) Приложение абсолютно стороннее. Оно генерирует текстовый файл, который и нужно постоянно анализировать.
2) Смысл в том, что все время потраченное на получение, анализ и вывод результата от записи в нужный файл сторонней программой строки должно укладываться в 50-100 миллисекунд.
Еще дополнительный момент к этому - в секунду в файл пишется порядка 5-10 строк в определенных ситуациях. Критичен порядок анализа.
3) Если бы пригляделись - я 3жды указывал пример строки для анализа.
4) В моем понимании "чтение не отходя от кассы". Т.е. постоянное отслеживание состояния файла и обработка ново поступивших строк.

Автор: ksnk 23.4.2012, 12:05
Чем меньше регулярка тем быстрее работают с ней функции. Так что разумнее не делать preg_match all на всю строку, а порезать ( explode ) по закрывающим квадратным скобкам на блоки информации и анализировать их отдельно. Первую сразу преобразовывать во время.
Регулярку, насколько хватило моих телепатических способностей, я бы переписал так
Код

$reg='~\[([\w\s]+)\W(.*)\W~';

Хотя в телепатии не силен и что там на самом деле надо - не понимаю.

С форматом нифига не ясно. Строка состоит из даты в квадратных скобках и информации в крадратных скобках. В каком виде хочется получить эту информацию?

Функция чтения содержит классическую ошибку  smile 

Если строки в файле появляются быстрее, чем $config['timeout'], то чтение будет идти все равно со скоростью не больше 1 строка в  $config['timeout'] и `актуальность` пролетает.

нужно читать в цикле из файла, пока не прочитает пустую строку и только после этого можно спать.

Автор: Kolgarn 23.4.2012, 15:07
Цитата(ksnk @ 23.4.2012,  12:05)
Чем меньше регулярка тем быстрее работают с ней функции. Так что разумнее не делать preg_match all на всю строку, а порезать ( explode ) по закрывающим квадратным скобкам на блоки информации и анализировать их отдельно. Первую сразу преобразовывать во время.
Регулярку, насколько хватило моих телепатических способностей, я бы переписал так
Код

$reg='~\[([\w\s]+)\W(.*)\W~';

Хотя в телепатии не силен и что там на самом деле надо - не понимаю.

С форматом нифига не ясно. Строка состоит из даты в квадратных скобках и информации в крадратных скобках. В каком виде хочется получить эту информацию?

Функция чтения содержит классическую ошибку  smile 

Если строки в файле появляются быстрее, чем $config['timeout'], то чтение будет идти все равно со скоростью не больше 1 строка в  $config['timeout'] и `актуальность` пролетает.

нужно читать в цикле из файла, пока не прочитает пустую строку и только после этого можно спать.

Да я так и делаю. С Ipad'a сижу вот и скинул код, что успел вспомнить)
По explode у меня проблема в том, что переодически есть и другие типы скобок -_-

Спасибо за совет по разрезанию. Признаться не думал, что отдельные преги будут быстрее.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)