Показать полную графическую версию : Парсинг XML/TXT
Доброго всем времени суток, опять обращаюсь за помощью )
Суть такова, имеется xml-файл (мноооооого строк), ну даже наверное точнее будет сказать txt, ибо как тэги там непонятные, в некоторых строках содержатся такие записи -
NUM="1234567890" и MAIL="mail@mail.ru"
соответственно в одной строке номеру соответствует мыльник, кое-где мыльников нет
Нужно извлечь в другой файл номера и адреса, т.е.
1234567890 mail@mail.ru
0987654321 mail2@mail.ru
....
Возможно ли?
Заранее спасибо!
имеется xml-файл (мноооооого строк) »
Сколько именно?
Anonymоus
17-07-2012, 00:01
Вариант с использованием grep (http://gnuwin32.sourceforge.net/packages/grep.htm). Он основан на регулярных выражениях, поэтому универсален и не зависит от тэгов XML или чего-то ещё. Главное для составления пары "телефон-email" это то, чтобы они оба находились на одной строке.
Распознаваемые форматы номеров:
123-456-7890
(123)456-7890
123 456 7890
1234567890
Файл, на котором проверялась работа скрипта:
NUM="1234567890" MAIL="mail@mail.ru"
NUM="0987654321" MAIL="test@test.test.com"
NUM="0851236214"
0987654320
NUM="3333333333" MAIL="12345_67890@gmail.com"
MAIL="abuse@hetzner.de"
admin@test.com
NUM="0000000000" MAIL="000@ya.ru"
support@leaseweb.com (111)2223334
Скрипт:
@Echo Off
Set Path=%Path%;%CD%\bin
Set XMLFile=file.txt
:: Получаем адреса почты с помощью регулярного выражения, обязательно проверяем
:: номер строки для составления пар. Последний номер строки пишется во временную
:: переменную, нужную для дальнейшей работы цикла, выдающего данные в два столбца.
For /F "tokens=1,* delims=:" %%A In ('grep -Eiorhn "([[:alnum:]_.-]+@[[:alnum:]_.-]+?\.[[:alpha:].]{2,6})" "%XMLFile%"') Do (
Set EMail_%%A=%%B
Set EMails=%%A
)
:: Проделываем то же самое с телефонами.
For /F "tokens=1,* delims=:" %%A In ('grep -oin "\(([0-9]\{3\})\|[0-9]\{3\}\)[ -]\?[0-9]\{3\}[ -]\?[0-9]\{4\}" "%XMLFile%"') Do (
Set Phone_%%A=%%B
Set Phones=%%A
)
:: Определяем максимальное число результатов для работы For /L.
If %EMails% GEQ %Phones% (Set Matches=%EMails%) Else (Set Matches=%Phones%)
SetLocal EnableDelayedExpansion
:: Добавляем один таб к не пустым значениям и два - к пустым. Отсекаем оба
:: пустых через grep -v. Это обеспечивает ровную таблицу, даже если число
:: телефонов и ящиков непарное, либо в строке указан лишь один из них.
Set i=0
For /L %%A In (1,1,%Matches%) Do (
If Defined Phone_%%A (Set Phone_%%A=!Phone_%%A! ) Else (Set Phone_%%A= )
If Defined EMail_%%A (Set EMail_%%A=!EMail_%%A! ) Else (Set EMail_%%A= )
:: Считаем проценты выполнения, свистоперделка, но пусть будет
Set /A i+=1
Set /A Progress=i*100/%Matches%||Set Progress= 0
If !Progress! LSS 10 (
Set Progress= !Progress!
) Else (
If !Progress! LSS 100 Set Progress= !Progress!
)
Echo !Progress!%% !Phone_%%A!!EMail_%%A!|grep -vi "(ECHO)"
:: Выводим те же данные в файл
Echo !Phone_%%A!!EMail_%%A!|grep -vi "(ECHO)">>out.txt
)
Pause&Exit
.....честно говоря слов нет. Профессионально. СПАСИБО!
Только вопрос нарисовался )
Если регулярку по номерам обрезать только до поиска 1234567890 (номера только такого формата, это не телефоны а уникальные номера) скорость поиска увеличится?
Можно ли разделить не табами а ";" ?
И на Вашем файле тестовом отлично отработал, а на моём в ~6000 тыс. строк, тоже всё нашёл, но сам не завершился, стал крутить до бесконечности, выдавая -
"Неверное число. Числа ограничены 32 битами чётности. 0%" (точнее это выдавать он начал сразу, но отбирал данные)
пока сам не прервал процесс. (это судя по-всему из-за процентов выполнения), но и с отключенным этим блоком, всё равно, не завершает процесс
Anonymоus
17-07-2012, 10:15
mxm199, нет, повышения быстродействия не будет, т.к. grep отрабатывает всю регулярку целиком за один запуск. Если бы я каждый раз на определённый шаблон номера запускал по процессу grep'а, тогда стоило бы оптимизировать.
Сколько строк в файле?
Попробуйте вот это, тут убрано всё лишнее и разделитель изменён на точку с запятой. Кроме того, быстродействие повышено из-за фильтрации пустых строк через If, а не grep, как в прошлом варианте.
@Echo Off
Set Path=%Path%;%CD%\bin
Set XMLFile=file.txt
For /F "tokens=1,* delims=:" %%A In ('grep -Eiorhn "([[:alnum:]_.-]+@[[:alnum:]_.-]+?\.[[:alpha:].]{2,6})" "%XMLFile%"') Do (Set EMail_%%A=%%B&Set EMails=%%A)
For /F "tokens=1,* delims=:" %%A In ('grep -oin "\(([0-9]\{3\})\|[0-9]\{3\}\)[ -]\?[0-9]\{3\}[ -]\?[0-9]\{4\}" "%XMLFile%"') Do (Set Phone_%%A=%%B&Set Phones=%%A)
If %EMails% GEQ %Phones% (Set Matches=%EMails%) Else (Set Matches=%Phones%)
SetLocal EnableDelayedExpansion
For /L %%A In (1,1,%Matches%) Do (
Set Out=!Phone_%%A!;!EMail_%%A!
If Not "!Out!"==";" Echo !Out!>>"out.txt"
)
Pause&Exit
строк изначально было порядка 6000, но я обрезал до 20, смысл тот же остался (на старом варианте)
на этом тоже самое, т.е. Ваш тестовый отлично отрабатывает и выходит, на моём файле ни в какую, тоже отрабатывает, всю информацию выбирает, но закрываться не хочет, только контрол-с помогает...
п.с. и всё-таки с табами оказалось лучше, извиняюсь )
Anonymоus
17-07-2012, 11:02
Пример файла можно?
Anonymоus
17-07-2012, 12:14
mxm199, убрал универсальные регэкспы, заточил под тот формат файла, что вы мне дали.
@Echo Off
SetLocal EnableDelayedExpansion
Set Path=%Path%;%CD%\bin
Set XMLFile=file.txt
For /F "tokens=1,3 delims==:" %%A In ('grep -ion "EMAIL=.[^ =]*." "%XMLFile%"') Do (
Set EMail=%%B&Set EMail=!EMail:"=!
Set EMail_%%A=!EMail!
Set EMails=%%A
)
For /F "tokens=1,3 delims==:" %%A In ('grep -ion "PHONE=.[^ =]*." "%XMLFile%"') Do (
Set Phone=%%B&Set Phone=!Phone:"=!
Set Phone_%%A=!Phone!
Set Phones=%%A
)
If %EMails% GEQ %Phones% (Set Matches=%EMails%) Else (Set Matches=%Phones%)
For /L %%A In (1,1,%Matches%) Do (
Set Out=!Phone_%%A! !EMail_%%A!
If Not "!Out!"==" " Echo !Out!
)
Pause&Exit
) работает! КРАСОТА! Спасибо!
для вывода в файл добавляю строку
Echo !Phone_%%A!!EMail_%%A!|grep -vi "(ECHO)">>out.txt
?
Anonymоus
17-07-2012, 12:34
Для вывода в файл заменяете
If Not "!Out!"==" " Echo !Out!
на
If Not "!Out!"==" " Echo !Out!>>"out.txt"
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.
Available in ZeroNet 1osznRoVratMCN3bFoFpR2pSV5c9z6sTC