![]() |
|
Модераторы: korob2001, ginnie |
![]()
|
|
| DooZ |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 206 Регистрация: 25.11.2005 Репутация: нет Всего: 1 |
задача следующая:
есть файл со словами (очень большой, например 500 мегабайт, или 10.000.000 слов, как пример) мама смотрит в окно моя книга очень интересная книга и авто не совместимы все слова в столбик есть второй файл, со словами по которым делать выборку, пример: авто окно книга суть скрипта следующая: поочередно берем слова из второго файла и вытягиваем слова из первого т.е.
как видите, в первом файле могут быть строки вроде: книга и авто не совместимы в свою очередь во втором файле мы видим что нам нужны все строки где есть слово: "авто" и "книга" т.е. мы должды записать строку: "книга и авто не совместимы" в файл: "авто" И (!) эту же строку записать в файл: "книга" т.е. вариант с объединением всех запросов для нахождения в один регекс не катит т.к. будет найдено только одно совпадение посоветовали сделать сначала выборку путем комманды: "cat $file|grep -P '(?:^|\s+)(?:окно|авто|книга)(?:\s+|$)' >tmp/complete" и потом уже разбирать файл complete построчно НО очень долго получается разбирать его т.е. cat + grep работает очень быстро а вот выборка по нужным запросом долго (файл в миллион строк, разбирается около часа) т.е. получается в данном случае нам надо три запроса: окно книга авто т.е. если cat + grep насобирал миллион записей, то при выборке будет обработано 3.000.000 записей у меня этих запросов сотни, соответсвенно кол-во выборок увеличивается не по детски =) как быть? кто что подскажет? можно в аську: 9603308 (можно за денежку, если действительно быстро будет работать, о цене договоримся) заранее благодарю |
|||
|
||||
| arto |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1495 Регистрация: 31.10.2004 Репутация: 38 Всего: 40 |
grep "\\b$word\\b" ?
+ распарралелить по возможности |
|||
|
||||
| DooZ |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 206 Регистрация: 25.11.2005 Репутация: нет Всего: 1 |
поточнее можно?
мне надо каждую найденую строку У КАЖДОГО запроса записать в свой файл т.е. если в файле номер 1 есть строка: ааа ббб ввв ггг ддд а в файле 2 в котором нужные мне запросы есть два запроса: ббб ддд надо записать в два файла эту строку в файл: ббб и в файл: ддд |
|||
|
||||
| arto |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1495 Регистрация: 31.10.2004 Репутация: 38 Всего: 40 |
1. поделить второй список по 20 слов, например.
2. запускать по 20 процессов grep с выводом в нужный файл 3. удалить пустые файлы. 4. простой греп быстрее, чем perl regexp |
|||
|
||||
| DooZ |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 206 Регистрация: 25.11.2005 Репутация: нет Всего: 1 |
разделение на процессы не дает скорости, процессор один и толку делить нет, проверено
Добавлено через 2 минуты и 30 секунд проблемма не у grep, а в том что много запросов нужных мне, и приходится перебирать массив (хеш) и работать с каждым запросом на каждой строке если запросов 100, то на одну строку идет 100 проверок и т.д. в этом и проблема! почему приходится перебирать цикл? потому что мне надо на каждый запрос проверить строку, и если в этой строке есть запрос надо записать его в файл Добавлено через 11 минут и 12 секунд вот код тот что щас работает:
|
|||
|
||||
| arto |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1495 Регистрация: 31.10.2004 Репутация: 38 Всего: 40 |
тогда вам надо подготовить списки под задачу заранее.
|
|||
|
||||
| DooZ |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 206 Регистрация: 25.11.2005 Репутация: нет Всего: 1 |
т.е. подготовить?
они и так подготовлены в файле1, список строк на проверку в файле2, список слов которые мне нужно выдирать из файла1, что тут не подготовлено? или я чего-то не понимаю, или Вы меня |
|||
|
||||
| arto |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1495 Регистрация: 31.10.2004 Репутация: 38 Всего: 40 |
не понимаете, да.
например -- адреса всех слов в первом файле, с длиной. тогда сможете сократить перебор по длине. еще можете проиндексировать по первой букве. делать это надо не сейчас, а когда собирается первый файл. |
|||
|
||||
| sir_nuf_nuf |
|
||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 920 Регистрация: 6.1.2008 Репутация: 14 Всего: 31 |
так...если хотим простое решение, то на мой взгляд их 2
в обоих случаях - 2 цикла , один в другом. в первом проходим по всем строкам, для каждой строки ищем ключи:
или второй вариант - для каждого ключа полностью просматриваем файл с данными
какой из них быстрее зависит от соотношений количества ключей и длинны файла с данными. подозреваю, что в большинстве случаев быстрее первый. есть еще вариант - засунуть перебор шаблонов в регулярку:
здесь перебор ключей осуществляется движком regex. Не думаю, что он делает оптимизацию для поиска по нескольким ключам, скорее всего просматривает строку на наличие каждго ключа последовательно. Если вам нужен _быстрый_ поиск по нескольким ключам - заведите новый топик и изучите алгоритмы =) |
||||||
|
|||||||
| DooZ |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 206 Регистрация: 25.11.2005 Репутация: нет Всего: 1 |
2sir_nuf_nuf
первый вариант теряет всю скорость, если регекс делать таким: (?:^|\s+)$_(?:\s+|$) что ознатает что нужный запрос может быть в начале, после него могут быть пробелы или конец текста или в конце или перед и после пробелы и т.д. а так и надо искать, ибо твой вариант где просто $_ будет искать например: запрос: машина -> у меня есть машина (годится) -> у друга есть машина (годится) -> естьмашина (не годится, а твой вариант возьмет его!) есть еще мысли как ускорить? |
|||
|
||||
| DooZ |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 206 Регистрация: 25.11.2005 Репутация: нет Всего: 1 |
третий вариант очень быстрый, но в нем минус, если он встречает первое нужное слово в строке, то если даже в этой строке есть второй нужное слово, он его уже не запишет!
|
|||
|
||||
| DooZ |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 206 Регистрация: 25.11.2005 Репутация: нет Всего: 1 |
вроде заработал третий пример вот так:
foreach my $str (<STRS>) { if ($str =~ /$compiled/igs) { foreach my $file (split(/\s+/, $str)) { next unless (exists $handles{$file}); my $h = $handles{$file}; print $h $str; } } } скорость на 160 запросах, и 100.000 строк файл первый, 1.5 секунды первый пример справлялся за 60 секунд |
|||
|
||||
| sir_nuf_nuf |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 920 Регистрация: 6.1.2008 Репутация: 14 Всего: 31 |
насчет третьего варианта - ты не прав. \
там специально стоит модификатор g и поиск в списковом контексте. так что третий вариант не будет останавливаться после первого совпадения. (?:^|\s+)$_(?:\s+|$) -- на счет этого я не подумал.. действительно нужно искать слова целиком только шаблон этот записывается так: \b$_\b |
|||
|
||||
| DooZ |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 206 Регистрация: 25.11.2005 Репутация: нет Всего: 1 |
а ты проверь третий пример, без моего добавления. он именно находит первое совпадение и все...
|
|||
|
||||
| DooZ |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 206 Регистрация: 25.11.2005 Репутация: нет Всего: 1 |
щас проверил четвертый вариант
работает на 100к базе при 158 запросах за 0.6 секунды |
|||
|
||||
![]()
|
| Правила форума "Perl" | |
|
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Perl: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |