Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Парсинг XML/TXT (http://forum.oszone.net/showthread.php?t=238684)

mxm199 16-07-2012 14:12 1952761

Парсинг XML/TXT
 
Доброго всем времени суток, опять обращаюсь за помощью )
Суть такова, имеется xml-файл (мноооооого строк), ну даже наверное точнее будет сказать txt, ибо как тэги там непонятные, в некоторых строках содержатся такие записи -
NUM="1234567890" и MAIL="mail@mail.ru"
соответственно в одной строке номеру соответствует мыльник, кое-где мыльников нет
Нужно извлечь в другой файл номера и адреса, т.е.
1234567890 mail@mail.ru
0987654321 mail2@mail.ru
....
Возможно ли?


Заранее спасибо!

Iska 16-07-2012 17:19 1952918

Цитата:

Цитата mxm199
имеется xml-файл (мноооооого строк) »

Сколько именно?

Anonymоus 17-07-2012 00:01 1953167

Вариант с использованием grep. Он основан на регулярных выражениях, поэтому универсален и не зависит от тэгов 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


mxm199 17-07-2012 09:52 1953322

.....честно говоря слов нет. Профессионально. СПАСИБО!

Только вопрос нарисовался )
Если регулярку по номерам обрезать только до поиска 1234567890 (номера только такого формата, это не телефоны а уникальные номера) скорость поиска увеличится?

Можно ли разделить не табами а ";" ?

И на Вашем файле тестовом отлично отработал, а на моём в ~6000 тыс. строк, тоже всё нашёл, но сам не завершился, стал крутить до бесконечности, выдавая -
"Неверное число. Числа ограничены 32 битами чётности. 0%" (точнее это выдавать он начал сразу, но отбирал данные)
пока сам не прервал процесс. (это судя по-всему из-за процентов выполнения), но и с отключенным этим блоком, всё равно, не завершает процесс

Anonymоus 17-07-2012 10:15 1953335

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


mxm199 17-07-2012 10:55 1953359

строк изначально было порядка 6000, но я обрезал до 20, смысл тот же остался (на старом варианте)
на этом тоже самое, т.е. Ваш тестовый отлично отрабатывает и выходит, на моём файле ни в какую, тоже отрабатывает, всю информацию выбирает, но закрываться не хочет, только контрол-с помогает...

п.с. и всё-таки с табами оказалось лучше, извиняюсь )

Anonymоus 17-07-2012 11:02 1953368

Пример файла можно?

mxm199 17-07-2012 11:34 1953386

Послал в личку

Anonymоus 17-07-2012 12:14 1953418

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


mxm199 17-07-2012 12:28 1953437

) работает! КРАСОТА! Спасибо!

для вывода в файл добавляю строку
Echo !Phone_%%A!!EMail_%%A!|grep -vi "(ECHO)">>out.txt
?

Anonymоus 17-07-2012 12:34 1953442

Для вывода в файл заменяете
Код:

        If Not "!Out!"=="        " Echo !Out!
на
Код:

        If Not "!Out!"=="        " Echo !Out!>>"out.txt"


Время: 16:24.

Время: 16:24.
© OSzone.net 2001-