![]() |
|
Модераторы: korob2001, ginnie |
![]()
|
|
| allinia |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 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вательно записывал все комбинации Бегинов и эндов в соответствующие элементы массива, я никак не могу придумать. Помогите, пожалуйста! |
|||
|
||||
| ginnie |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1287 Регистрация: 6.1.2008 Где: Москва Репутация: 38 Всего: 49 |
Уважаемая allinia, попробуйте
не понятно только назначение $ (получается подстановка значения переменной $typ), а также \w и \W в одной группе -------------------- Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг) |
|||
|
||||
| allinia |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 4 Регистрация: 14.10.2008 Репутация: нет Всего: нет |
ginnie!
Спасибо большое, получается! И я ведь сама думала что мне обязательно нужeн знак вопроса, только ставила я его все время не туда! Переменную мне нужно подставлять, так как нужно по-разному обрабатывать данные в зависимости от типа. а \w и \W, потому что в тексте содержится огромное количество всяких управляющих символов, начиная с перевода каретки, перевода строки, всяких эскейпов и т.п и без этого он считывать весь блок ну никак не хочет. А еще вопрос у меня возник, а можно ли как-то сравнить полученные блоки между собой, не используя про этом массивы? В моем случае в каждом блоке содержится дата и время и мне нужно исключить повторяющиейся блоки. Т.е. нужно сравнивать тип, дату и время. Так как Перл лучше всего (быстрее всего) работает со строками, а не с массивами, то хотелось бы по максимуму использовать эту его особенность. |
|||
|
||||
| KSURi |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 887 Регистрация: 8.6.2006 Где: Russia Репутация: 20 Всего: 27 |
У вас в примере текст (BEGIN, END) в нижнем регистре, а в регексе в верхнем. Либо приведите к одному регистру, либо включите режим case-insensitive (//i)
-------------------- Died at Life.pl line 21 |
|||
|
||||
| ginnie |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1287 Регистрация: 6.1.2008 Где: Москва Репутация: 38 Всего: 49 |
allinia, предлагаю сделать чтение из файла построчным и обрабатывать прочитанный целиком блок. При этом формировать из типа, даты и времени ключ хеша для исключения повторений.
-------------------- Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг) |
|||
|
||||
| allinia |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 4 Регистрация: 14.10.2008 Репутация: нет Всего: нет |
ginnie,
я так и делала, пока данные были более-менее обозримыми. Для каждого блока в хэш-таблице был ключ "тип-версия-дата". Только, плохо разбираясь в регулярных выражениях, делила я блоки с помошью функции split(). Но теперь размер получаемых исходных текстовых файлов стал таким оргомным, что потребовалось сначала делить данные по версиям и типам, удаляя при этом повторяющиеся данные. С массивами это работает медленно, хотелось бы оптимизировать, а заодно и научиться работать с регулярными выражениями. Спасибо Вам за подсказку! KSURi, я, конечно же, здесь для примера писала все маленькими буквами, а строчку кода взяла реальную, получилась путаница. В следующий раз буду внимательнее. Спасибо. |
|||
|
||||
| arto |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 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 }'
|
|||
|
||||
| amg |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1145 Регистрация: 3.8.2006 Где: Новосибирск Репутация: 38 Всего: 50 |
[\w\W] по сути означает любой символ, для которого есть специальное обозначение, . (точка). Но чтобы считывался весь блок, . (точка) должна подходить и концу строки. А для этого есть специальный модификатор, s. Т.е. так
Кстати, что за модификатор c? Массивы сами по себе -- это не медленно, смотря как их использовать. Приведите, пожалуйста, пример Ваших данных (реальных, можно файл приложить), и что нужно получить, тогда помочь Вам будет гораздо легче. |
|||
|
||||
| allinia |
|
||||||
|
Новичок Профиль Группа: Участник Сообщений: 4 Регистрация: 14.10.2008 Репутация: нет Всего: нет |
amg,
я пробовала модификатор s. В моем случае он не подходит. Не могу четко обьяснить почему, но думаю из-за каких-то особых символов, содержащихся в файле, тот кусок, что мне надо, никак не хотел выделяться. Методом проб и ошибок пришла к варианту \w\W.
Модификатор c используется вместе с модификатором g ,для того чтобы последующий поиск продолжался с того места, где было последнее совпадение. Но Вы правы, в этом случе это излишне.
Даже не знаю, как получше обьяснить, что мне надо. Есть исходный текстовый файл, в котором содержатся блоки данных о некоторых устройствах. Каждый блок может повторяться в текстовом файле, но анализироваться он должен только один раз. Я храню эти блоки в хэш-таблицах, где ключом является связка "номерПрибора-тип-версия-дата". Данные я после всяких манипуляций с ними заношу в соответствующие Ехел таблицы. Пока данных было не такое количество, все работало. Сейчас возникла проблема, что данные инконсистентны, возможно, ошибка в анализаторе, но при таком количестве данных проверить я это физически не могу (например, для одного типа одной версии есть 244 прибора, а типов и версий тоже много). Сейчас мне нужно упростить задачу тем, чтобы хотя бы разделить большой файл со всеми типами на несколько меньших файлов, каждый со своим типом. при этом для ставнения на идентичность блоков (чтобы удалить лишние) мне нужно использовать довольно длинную цепочку - это номер + тип + дата + время + еще несколько параметров, которые в блоке стоят совсем даже не рядом друг с другом. в общем я пока не могу придумать, как это лучше сделать. Я, конечно, могу приложить реальные файлы, но не знаю, поможет ли это вам понять мою задачу, там все по-немецки (я работаю в Германии). Особенно, учитывая, что я сама не могу нормально обьяснить, чего мне надо Я подумаю до завтра, как мне получше сформулировать мою проблему. Большое спасибо за желание помочь! |
||||||
|
|||||||
| IceSunrise |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 61 Регистрация: 7.4.2008 Где: Санкт-Петербург Репутация: 3 Всего: 3 |
Поправьте меня, но в perl нет модификатора 'c' или скажите пожалуйста, где об этом можно почитать?
|
|||
|
||||
| ginnie |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1287 Регистрация: 6.1.2008 Где: Москва Репутация: 38 Всего: 49 |
allinia, . с модификатором /s должна работать корректно, проверьте еще раз, т.к. \w\W - вариант логически неверный (он работает, но вызывает недоумение у других разработчиков).
Модификатор /c используется для сохранения места последнего успешного совпадения при отсутствии совпадения в очередной проверке. Могу предложить сделать структуру в виде вложенных хешей:
это должно упростить проверку целостности данных. Добавлено через 1 минуту и 1 секунду IceSunrise, читайте perldoc perlre -------------------- Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг) |
|||
|
||||
| IceSunrise |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 61 Регистрация: 7.4.2008 Где: Санкт-Петербург Репутация: 3 Всего: 3 |
ginnie, ага, спасибо, нашел в perlretut, секция Global matching. Нужно сказать никогда не использовал
|
|||
|
||||
![]()
|
| Правила форума "Perl" | |
|
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Perl: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |