Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> регулярное выражение к строке с повторяющимися бло, помогите блоки записать в массив 
:(
    Опции темы
allinia
Дата 14.10.2008, 13:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 14.10.2008

Репутация: нет
Всего: нет



Помогите, пожалуйста, составить регулярное выражение для следующего случая.

Есть огромный (100 Мб) текстовый файл однотипных данных, который я считываю как строку.
Данные вида: 

begin typ1
string 1.1
...
string 1.n
end

begin typ2
string 2.1
...
string 2.n
end
...
begin typN
string N.1
...
string N.n
end


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

('begin typ1 string 1.1 ... string 1.n end', begin typ2 string 2.1 ... string 2.n end',..., begin typN string N.1 ... string N.n end') 

пробовала так:
@result_array = ($orig_text =~ m/(BEGIN\s*$typ\s*[\w\s\d\.\W]*END)/gc);

но в первый элемент массива записывается весь текст. Т.е. он берет первый Бегин и самый последний Енд. А как сделать, чтобы он последoвательно записывал все комбинации Бегинов и эндов в соответствующие элементы массива, я никак не могу придумать. 
Помогите, пожалуйста!


PM MAIL   Вверх
ginnie
Дата 14.10.2008, 13:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



Уважаемая allinia, попробуйте

Код

@result_array = ($orig_text =~ m/(BEGIN\s*$typ\s*[\w\s\d\.\W]*?END)/gc);


не понятно только назначение $ (получается подстановка значения переменной $typ), а также \w и \W в одной группе 


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
allinia
Дата 14.10.2008, 14:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 14.10.2008

Репутация: нет
Всего: нет



ginnie!
Спасибо большое, получается! И я ведь сама думала что мне обязательно нужeн знак вопроса, только ставила я его все время не туда!

Переменную мне нужно подставлять, так как нужно по-разному обрабатывать данные в зависимости от типа.
а  \w и \W, потому что в тексте содержится огромное количество всяких управляющих символов, начиная с перевода каретки, перевода строки, всяких эскейпов и т.п и без этого он считывать весь блок ну никак не хочет.


А еще вопрос у меня возник, а можно ли как-то сравнить полученные блоки между собой, не используя про этом массивы?
В моем случае в каждом блоке содержится дата и время и мне нужно исключить повторяющиейся блоки. Т.е. нужно сравнивать тип, дату и время.
Так как Перл лучше всего (быстрее всего) работает со строками, а не с массивами, то хотелось бы по максимуму использовать эту его особенность.
PM MAIL   Вверх
KSURi
Дата 14.10.2008, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 887
Регистрация: 8.6.2006
Где: Russia

Репутация: 20
Всего: 27



У вас в примере текст (BEGIN, END) в нижнем регистре, а в регексе в верхнем. Либо приведите к одному регистру, либо включите режим case-insensitive (//i)


--------------------
Died at Life.pl line 21
PM Jabber   Вверх
ginnie
Дата 14.10.2008, 14:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



allinia, предлагаю сделать чтение из файла построчным и обрабатывать прочитанный целиком блок. При этом формировать из типа, даты и времени ключ хеша для исключения повторений.


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
allinia
Дата 14.10.2008, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 14.10.2008

Репутация: нет
Всего: нет



ginnie, 

я так и делала, пока данные были более-менее обозримыми. Для каждого блока в хэш-таблице был ключ "тип-версия-дата". Только, плохо разбираясь в регулярных выражениях, делила я блоки с помошью функции split().

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

Спасибо Вам за подсказку!

KSURi, я, конечно же, здесь для примера писала все маленькими буквами, а строчку кода взяла реальную, получилась путаница. В следующий раз буду внимательнее. Спасибо.
 
PM MAIL   Вверх
arto
Дата 14.10.2008, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1495
Регистрация: 31.10.2004

Репутация: 38
Всего: 40



perl -MData::Dumper -ne 'chomp; if (m#^begin\s+(\w+)#..m#^end#) { push @{$a->{$e = $1 || $e}},$_ } END { print Dumper $a }'
PM MAIL ICQ   Вверх
amg
Дата 14.10.2008, 15:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



Цитата(allinia @  14.10.2008,  14:12 Найти цитируемый пост)
а  \w и \W, потому что в тексте содержится огромное количество всяких управляющих символов, начиная с перевода каретки, перевода строки, всяких эскейпов и т.п и без этого он считывать весь блок ну никак не хочет.
[\w\W] по сути означает любой символ, для которого есть специальное обозначение, . (точка). Но чтобы считывался весь блок, . (точка) должна подходить и концу строки. А для этого есть специальный модификатор, s. Т.е. так
Код
@result_array = ($orig_text =~ m/(BEGIN\s*$typ\s*.*?END)/gcs);

Кстати, что за модификатор c?

Цитата(allinia @  14.10.2008,  14:34 Найти цитируемый пост)
Но теперь размер получаемых исходных текстовых файлов стал таким оргомным, что потребовалось сначала делить данные по версиям и типам, удаляя при этом повторяющиеся данные. С массивами это работает медленно, хотелось бы оптимизировать
Массивы сами по себе -- это не медленно, смотря как их использовать. Приведите, пожалуйста, пример Ваших данных (реальных, можно файл приложить), и что нужно получить, тогда помочь Вам будет гораздо легче.

PM MAIL   Вверх
allinia
Дата 14.10.2008, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 14.10.2008

Репутация: нет
Всего: нет



amg,

Цитата

][\w\W] по сути означает любой символ, для которого есть специальное обозначение, . (точка). Но чтобы считывался весь блок, . (точка) должна подходить и концу строки. А для этого есть специальный модификатор, s. 


я пробовала модификатор s. В моем случае он не подходит. Не могу четко обьяснить почему, но думаю из-за каких-то особых символов, содержащихся в файле, тот кусок, что мне надо, никак не хотел выделяться. Методом проб и ошибок пришла к варианту \w\W.

Цитата

Кстати, что за модификатор c?


Модификатор c используется вместе с модификатором g ,для того чтобы последующий поиск продолжался с того места, где было последнее совпадение. Но Вы правы, в этом случе это излишне. 


Цитата

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


Даже не знаю, как получше обьяснить, что мне надо. Есть исходный текстовый файл, в котором содержатся блоки данных о некоторых устройствах. Каждый блок может повторяться в текстовом файле, но анализироваться он должен только один раз. Я храню эти блоки в хэш-таблицах, где ключом является связка "номерПрибора-тип-версия-дата".  Данные я после всяких манипуляций с ними заношу в соответствующие Ехел таблицы. 
Пока данных было не такое количество, все работало. Сейчас возникла проблема, что данные инконсистентны, возможно, ошибка в анализаторе, но при таком количестве данных проверить я это физически не могу (например, для одного типа одной версии есть 244 прибора, а типов и версий тоже много). Сейчас мне нужно упростить задачу тем, чтобы хотя бы разделить большой файл со всеми типами на несколько меньших файлов, каждый со своим типом.

при этом для ставнения на идентичность блоков (чтобы удалить лишние) мне нужно использовать довольно длинную цепочку - это номер + тип + дата + время + еще несколько параметров, которые в блоке стоят совсем даже не рядом друг с другом. 

в общем я пока не могу придумать, как это лучше сделать. Я, конечно, могу приложить реальные файлы, но не знаю, поможет ли это вам понять мою задачу, там все по-немецки (я работаю в Германии).  Особенно, учитывая, что я сама не могу нормально обьяснить, чего мне надо  smile 
Я подумаю до завтра, как мне получше сформулировать мою проблему. Большое спасибо за желание помочь! 

PM MAIL   Вверх
IceSunrise
Дата 14.10.2008, 17:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 61
Регистрация: 7.4.2008
Где: Санкт-Петербург

Репутация: 3
Всего: 3



Поправьте меня, но в perl нет модификатора 'c' или скажите пожалуйста, где об этом можно почитать?
PM MAIL   Вверх
ginnie
Дата 14.10.2008, 17:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



allinia, . с модификатором /s должна работать корректно, проверьте еще раз, т.к. \w\W - вариант логически неверный (он работает, но вызывает недоумение у других разработчиков).

Модификатор /c используется для сохранения места последнего успешного совпадения при отсутствии совпадения в очередной проверке.

Могу предложить сделать структуру в виде вложенных хешей:

Код

$hash{$number}->{$type}{$date}{$time}...{$param_n} = $link_to_block_data;


это должно упростить проверку целостности данных.

Добавлено через 1 минуту и 1 секунду
IceSunrise, читайте perldoc perlre


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
IceSunrise
Дата 14.10.2008, 18:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 61
Регистрация: 7.4.2008
Где: Санкт-Петербург

Репутация: 3
Всего: 3



ginnie,  ага, спасибо, нашел в perlretut, секция Global matching. Нужно сказать никогда не использовал smile
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0561 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.