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

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

LAKERS824 28-06-2012 16:46 1942170

вывод строки из *.xml
 
Добрый день!

Есть папка, в которую закачиваются файлы с ftp несколько раз в день.
Названия файлов типа:3143719278_1605201290029.xml

Необходимо прочитать все файлы в папке, и вывести из каждого файла то, что содержится в строке

<InsuranceNumber>94595</InsuranceNumber> , т.е. в этом случае вывести 94595.

Причем итоговое значение д.б. таким : первая часть имени файла остается той же, т.е. 3143719278, а через _ добавляем 94595.

Получаем на выходе: 3143719278_94595

Если же поле InsuranceNumber пустое, то вывести 3143719278_0.



Каким образом это можно сделать или вообще можно?

Anonymоus 28-06-2012 17:05 1942185

Для работы скрипта нужен Grep из набора утилит GNU coreutils, портированный под Windows, плюс его зависимости. Рядом со скриптом создать директорию bin, куда и сложить бинарник грепа и либы, нужные для его работы.
Код:

@Echo Off
SetLocal EnableDelayedExpansion
Set Path=%Path%;%CD%\bin
Set XMLPath=D:\Temp\xmlfiles
For /F "delims=" %%F In ('Dir "%XMLPath%\*.xml" /B 2^>nul') Do (
        Set Prefix=&Set InsuranceNumber=0
        For /F "delims=_" %%P In ("%%~F") Do (Set Prefix=%%P)
        For /F "tokens=2 delims=><" %%N In ('grep -Eo "<InsuranceNumber>[^<]*</InsuranceNumber>" "%XMLPath%\%%F"') Do (
                If Not %%N==/InsuranceNumber Set InsuranceNumber=%%N
        )
        Echo !Prefix!_!InsuranceNumber!
)
Pause

Скрипт вместе с обвязкой (греп+зависимости) - http://rghost.ru/38920583

Исправил скрипт, вначале невнимательно прочел условие и не сделал обработку пустого значения.

LAKERS824 28-06-2012 17:15 1942190

Anonymоus, спасибо, заработало, НО:

Если поле InsuranceNumber содержит русские буквы, то получаем в итоге крякозябры, можно ли их исправить?

Anonymоus 28-06-2012 17:22 1942195

LAKERS824, об этом в вашем условии ни слова не было, предполагалось, что InsurcanceNumber состоит из цифр, судя по примеру. Смотрите, в какой кодировке ваши XML, и в какой кодировке сохранён скрипт. Он выводит только то, что получает из файла. Пусть даже в консоли выводятся кракозябры, если перенаправить их в файл - получится читаемый текст в той самой кодировке, в которой были XML-файлы.

LAKERS824 29-06-2012 08:48 1942512

Anonymоus, а как это закинуть в файл? у меня только первая строка в файл уходит.

LAKERS824 05-07-2012 16:48 1946545

Anonymоus, Еще такой момент, после знака _ м.б. различное кол-во символов (точка, 0, начинается с буквы, оканчивается буквой, более 5 символов, 5 символов.).

Так вот, можно ли сделать так, чтобы там где '_98765' (5 символов после _) или '_987654' (6 символов после _) - записывались в один файл, а все остальное переправлять в другой файл?

Anonymоus 05-07-2012 17:25 1946582

LAKERS824, перенаправляется в файл - вот так:
Код:

        Echo !Prefix!_!InsuranceNumber!>>"file.txt"
Вариант с выводом в два файла, в зависимости от длины строки после "_" :

Код:

@Echo Off
SetLocal EnableDelayedExpansion
Set Path=%Path%;%CD%\bin

Set XMLPath=D:\Temp\xmlfiles

For /F "delims=" %%F In ('Dir "%XMLPath%\*.xml" /B 2^>nul') Do (
        Set Prefix=&Set InsuranceNumber=0
        For /F "tokens=1,2 delims=_." %%P In ("%%~F") Do (Set Prefix=%%P&Set Suffix=%%Q)
        For /F "tokens=2 delims=><" %%N In ('grep -Eo "<InsuranceNumber>[^<]*</InsuranceNumber>" "%XMLPath%\%%F"') Do (
                If Not %%N==/InsuranceNumber Set InsuranceNumber=%%N
        )
        Call :StringLen "!Suffix!"
        If !$StringLen!==5 (Echo !Prefix!_!InsuranceNumber!>>"result5and6.txt")
        If !$StringLen!==6 (Echo !Prefix!_!InsuranceNumber!>>"result5and6.txt")
        If Not !$StringLen!==5 (
                If Not !$StringLen!==6 (
                        Echo !Prefix!_!InsuranceNumber!>>"result_other.txt"
                )
        )
)
Pause&Exit

:StringLen
:: Автор функции - amel27, http://forum.oszone.net/post-1162296-2.html
  Set $StringLen=0&Set $StringBuf=%~1
  If ""=="%~1" GoTo :EOF
:StringLenLoop
  Set /A $StringLen+=1
  Call Set $StringChr=%%$StringBuf:~%$StringLen%%%
  If ""=="%$StringChr%" GOTO :EOF
GoTo :StringLenLoop

Точки в части после "_" быть не должно.

LAKERS824 06-07-2012 08:49 1946922

3 вопросика:

1 Почему не должно быть точки? Если она все же есть, то в какой из файлов она уйдет? в result_other.txt?
2 Работает наполовину, файла result5and6.txt так и не создается - не нашел после выполнения команды данного файла.
3 И так где 5 знаков тоже вываливаются в result_other.txt

Anonymоus 06-07-2012 12:19 1947011

Точки не должно быть, потому что она используется как разделитель в delims, чтобы отделить и отбросить ненужное расширение файла.
Работает полностью, я протестировал вот на этом наборе файлов - http://rghost.ru/39065474

LAKERS824 06-07-2012 13:41 1947057

я наверное неправильно выразился.
Надо читать внутренний номер InsuranceNumber и если он 5 или 6, то в один файл, если он точка, ноль или отличается от 5 и 6, то в другой.
Все исправил сам, спасибо.

Anonymоus 06-07-2012 13:47 1947061

Вот, теперь всё предельно чётко, так бы сразу и сформулировали.
Код:

@Echo Off
SetLocal EnableDelayedExpansion
Set Path=%Path%;%CD%\bin

Set XMLPath=D:\Temp\xmlfiles

For /F "delims=" %%F In ('Dir "%XMLPath%\*.xml" /B 2^>nul') Do (
        Set Prefix=&Set InsuranceNumber=0
        For /F "tokens=1,2 delims=_" %%P In ("%%~F") Do (Set Prefix=%%P)
        For /F "tokens=2 delims=><" %%N In ('grep -Eo "<InsuranceNumber>[^<]*</InsuranceNumber>" "%XMLPath%\%%F"') Do (
                If Not %%N==/InsuranceNumber Set InsuranceNumber=%%N
        )
        Call :StringLen "!InsuranceNumber!"
        If !$StringLen!==5 (Echo !Prefix!_!InsuranceNumber!>>"result_5and6.txt")
        If !$StringLen!==6 (Echo !Prefix!_!InsuranceNumber!>>"result_5and6.txt")
        If Not !$StringLen!==5 (
                If Not !$StringLen!==6 (
                        Echo !Prefix!_!InsuranceNumber!>>"result_other.txt"
                )
        )
)
Pause&Exit

:StringLen
:: Автор функции - amel27, http://forum.oszone.net/post-1162296-2.html
  Set $StringLen=0&Set $StringBuf=%~1
  If ""=="%~1" GoTo :EOF
:StringLenLoop
  Set /A $StringLen+=1
  Call Set $StringChr=%%$StringBuf:~%$StringLen%%%
  If ""=="%$StringChr%" GOTO :EOF
GoTo :StringLenLoop


LAKERS824 06-07-2012 13:48 1947063

Anonymоus, огромнейшее спасибо.

LAKERS824 07-07-2012 00:30 1947404

По-умолчанию текстовый файл сохраняется в UTF формате. Можно ли сохранить его в ANSI?

Anonymоus 07-07-2012 00:46 1947417

LAKERS824, утилита Recode из пакета unxutils поможет вам.

LAKERS824 07-07-2012 01:26 1947438

Код:

recode -f utf8/crlf..cp1251 <D:\pronin\result5and6.txt >>D:\pronin\new_result5and6.txt
выдает пустой файл, но в ANSI, а не результат преобразования.

Anonymоus 07-07-2012 01:41 1947449

LAKERS824, попробуйте вот так:
Код:

@Echo Off
SetLocal EnableDelayedExpansion
Set Path=%Path%;%CD%\bin

Set XMLPath=D:\Temp\xmlfiles

For /F "delims=" %%F In ('Dir "%XMLPath%\*.xml" /B 2^>nul') Do (
        Set Prefix=&Set InsuranceNumber=0
        For /F "tokens=1,2 delims=_" %%P In ("%%~F") Do (Set Prefix=%%P)
        For /F "tokens=2 delims=><" %%N In ('grep -Eo "<InsuranceNumber>[^<]*</InsuranceNumber>" "%XMLPath%\%%F"') Do (
                If Not %%N==/InsuranceNumber Set InsuranceNumber=%%N
        )
        Call :StringLen "!InsuranceNumber!"
        If !$StringLen!==5 (Echo !Prefix!_!InsuranceNumber!|recode utf8..cp1251/>>"result_5and6.txt")
        If !$StringLen!==6 (Echo !Prefix!_!InsuranceNumber!|recode utf8..cp1251/>>"result_5and6.txt")
        If Not !$StringLen!==5 (
                If Not !$StringLen!==6 (
                        Echo !Prefix!_!InsuranceNumber!|recode utf8..cp1251/>>"result_other.txt"
                )
        )
)
Pause&Exit

:StringLen
:: Автор функции - amel27, http://forum.oszone.net/post-1162296-2.html
  Set $StringLen=0&Set $StringBuf=%~1
  If ""=="%~1" GoTo :EOF
:StringLenLoop
  Set /A $StringLen+=1
  Call Set $StringChr=%%$StringBuf:~%$StringLen%%%
  If ""=="%$StringChr%" GOTO :EOF
GoTo :StringLenLoop


LAKERS824 07-07-2012 17:00 1947657

при этом создается пустой файл result_5and6.txt, в нужной кодировке ANSI, а файл result_other.txt вообще не создается

Anonymоus 07-07-2012 17:18 1947666

LAKERS824, к сожалению, я не телепат, чтобы определить кодировку ваших xml-файлов. Судя по тому, что файлы с результатами создавались в utf-8, я предположил, что xml в такой же кодировке, и вписал пару "utf8..cp1251/" в скрипт. Уточните, в какой именно они кодировке и исправьте её в скрипте самостоятельно - либо приложите несколько заархивированных xml для образца, чтобы я сам исправил.

LAKERS824 07-07-2012 17:22 1947669

Вложений: 1
вложил один xml

Anonymоus 07-07-2012 17:45 1947682

Тип XML: Конец строки - win (CR+LF), Кодировка - UTF8 без BOM
Файл с результатом, без recode: Конец строки - win (CR+LF), Кодировка - UTF8 без BOM
Файл с результатом, в который всё писалось через recode: Конец строки - win (CR+LF), Кодировка - cp1251
Всё верно, пара кодировок правильная, вот результат обработки вашего xml:


Вы точно запускаете мой скрипт без модификаций? Файлы не должны создаваться пустыми, у меня всё работает, и на тестовых файлах, и на вашем xml.

LAKERS824 07-07-2012 20:09 1947745

Код:

@Echo on

SetLocal EnableDelayedExpansion
Set Path=%Path%;C:\Users\Diman\Desktop\KDL\grep+parseXML\bin

Set XMLPath=C:\Users\Diman\Desktop\KDL\XML

For /F "delims=" %%F In ('Dir "%XMLPath%\*.xml" /B 2^>nul') Do (
        Set Prefix=&Set InsuranceNumber=0
        For /F "tokens=1,2 delims=_." %%P In ("%%~F") Do (Set Prefix=%%P&Set Suffix=%%Q)
        For /F "tokens=2 delims=><" %%N In ('grep -Eo "<LastName>[^<]*</LastName>" "%XMLPath%\%%F"') Do (If Not %%N==/LastName Set LastName=%%N)
        For /F "tokens=2 delims=><" %%N In ('grep -Eo "<InsuranceNumber>[^<]*</InsuranceNumber>" "%XMLPath%\%%F"') Do (
                If Not %%N==/InsuranceNumber Set InsuranceNumber=%%N
        )
        Call :StringLen "!InsuranceNumber!"
        If !$StringLen!==5 (Echo !Prefix!_!InsuranceNumber!_!LastName!|recode utf8..cp1251/>>"C:\Users\Diman\Desktop\KDL\result5and6.txt")
        If !$StringLen!==6 (Echo !Prefix!_!InsuranceNumber!_!LastName!|recode utf8..cp1251/>>"C:\Users\Diman\Desktop\KDL\result5and6.txt")
        If Not !$StringLen!==5 (
                If Not !$StringLen!==6 (
                        Echo !Prefix!_!InsuranceNumber!_!LastName!|recode utf8..cp1251/>>"C:\Users\Diman\Desktop\KDL\result_other.txt"
                )
        )
)
Pause&Exit

:StringLen
:: Автор функции - amel27, http://forum.oszone.net/post-1162296-2.html
  Set $StringLen=0&Set $StringBuf=%~1
  If ""=="%~1" GoTo :EOF
:StringLenLoop
  Set /A $StringLen+=1
  Call Set $StringChr=%%$StringBuf:~%$StringLen%%%
  If ""=="%$StringChr%" GOTO :EOF
GoTo :StringLenLoop

Запускаю с небольшой модификацией, вытаскиваю еще и Фамилию дополнительно, не более

Anonymоus 07-07-2012 22:45 1947824

LAKERS824, попробуйте запустить вот этот скрипт: http://rghost.ru/39092099
Настройки пути к xml вынесены в файл settings.ini. На вашем файле отработало успешно.

LAKERS824 07-07-2012 23:04 1947830

В принципе работает, но я заметил следующее, если в строке

Код:

Set Path=%Path%;%CD%\bin
я пишу свой путь, т.е.
Код:

Set Path=%Path%;D:\KDL\grep+parseXML\bin
то файл и создается пустым. Не пойму в чем дело?

А если я оставляю
Код:

%CD%\bin
, то вроде все ок, я же ведь более нигде не указываю %CD%

блин, на XP работает, как описал выше, переношу те же файлы на Windows 7 64-бит, меняю только пути и опять создается пустой файл один

Anonymоus 07-07-2012 23:17 1947836

Объясните смысл замены %CD%\bin на вписанный вами вручную абсолютный путь? Не меняйте пожалуйста код, если он работает и нет веской причины его переделывать.
Почему именно после вашей модификации перестает работать точно не скажу, попробуйте сравнить вывод Echo %CD% с тем, что вы вписываете как абсолютный путь.

LAKERS824 07-07-2012 23:43 1947855

перенес на 2003 винду, тоже создается пустой файл.


Set Path=%Path%;%CD%\bin - эта строка указывает пусть к grep+parseXML?
Ведь у меня в папке, скажем D:\papka есть папка grep+parseXML\bin, а также в корне papka\bin - которая от recode.
Так верхний путь не может находить неверный путь?

Anonymоus 07-07-2012 23:50 1947866

Цитата:

Цитата LAKERS824
Set Path=%Path%;%CD%\bin - эта строка указывает пусть к grep+parseXML? »

Эта строка разворачивается в текущую директорию и её поддиректорию bin, где находятся все необходимые бинарники (grep, recode) и библиотеки (pcre, iconv, intl)
Цитата:

Цитата LAKERS824
а также в корне papka\bin - которая от recode »

Но зачем? Посмотрите на содержимое той директории bin, что в данном вам архиве, там уже есть recode.
Плюс к тому, преимущество записи Set Path=%Path%;%CD%\bin - в портабельности самого скрипта, в нем нету абсолютных путей, его можно переносить куда угодно, и на другом ПК он будет работать точно так же (если не забудут скопировать директорию bin вместе с ним).

LAKERS824 08-07-2012 00:09 1947877

спасибо, разобрался с папкой bin и все встало на свои места. СПАСИБО.


Время: 06:02.

Время: 06:02.
© OSzone.net 2001-