Войти

Показать полную графическую версию : Задача: парсинг текстового файла


Лео Lапыч
31-12-2015, 13:30
Добрый день, системные администраторы и программисты-разработчики!

Давно хочу решить одну задачку средствами командного интерпретатора Windows, но всё времени не хватает углубиться в тонкости языка.
Задача возникла как скрипт ловушки для системы управления версиями Subversion. В частном случае я её решил, но хотелось бы в общем.
Итак, внимание, задачка:

Исходные данные. Есть текстовый файл, структура которого следующая:
Path1 - Mask1_1
Mask1_...
Mask1_N-1
Mask1_N

Path... - Mask..._1
Mask..._...
Mask..._N-1
Mask..._N

PathM-1 - MaskM-1_1
MaskM-1_...
MaskM-1_N-1
MaskM-1_N

PathM - MaskM_1
MaskM_...
MaskM_N-1
MaskM_N
Пояснения: файл содержит путь, потом символы пробел, минус, пробел и первую маску; последующие маски, относящиеся к этому пути, начинаются с новой строки (CRLF); признаком окончания списка масок, относящихся к пути, являются пустая строка (CRLFCRLF) или конец файла. Дальше всё может повторится для другого пути. Количество путей и масок не ограничено (в разумных пределах).

Требуется получить в локальную переменную командного пакета строку вида:
%Result% = "Path1\Mask1_1 Path1\Mask1_... Path1\Mask1_N-1 Path1\Mask1_N ... Path...\Mask..._1 Path...\Mask..._... Path...\Mask..._N-1 Path...\Mask..._N PathM-1\MaskM-1_1 PathM-1\MaskM-1_... PathM-1\MaskM-1_N-1 PathM-1\MaskM-1_N PathM\MaskM_1 PathM\MaskM_... PathM\MaskM_N-1 PathM\MaskM_N"
То есть разложить этот файл в строку, содержащую пути с маской, разделённые пробелом. Кроме того, все символы разделителя пути / должны быть преобразованы в \.
Возможен, конечно, косяк, если в имени пути или маске содержатся пробелы, либо в имени пути содержатся подряд идущие символы пробел, минус, пробел. Но такие случаи пока от условий задачи отсечём.

Пример:
На основе файла
Projects/Builder - *.~*
*.$*
*.obj

Projects/CSharp - *.cache*
*.suo
Должна получится строка
Projects\Builder\*.~* Projects\Builder\*.$* Projects\Builder\*.obj Projects\CSharp\*.cache* Projects\CSharp\*.suo

Более высокоуровневые языки для решения использовать пока не хочу. Так что у кого на досуге будет время поломать голову, прошу поделиться мыслями.
Благодарен уже за уделённое внимание!

Foreigner
31-12-2015, 14:24
На основе файла »


@echo off
setlocal

for /f "tokens=*" %%i in (1.txt) do call:0 %%i
echo.
goto:eof

:0
if not "%2"=="" (0>nul set /p="%~1\%3 " & set p=%~1) else (0>nul set /p="%p%\%1 ")

Лео Lапыч
03-01-2016, 21:38
Спасибо, Иностранец. Честно говоря, это читерство какое-то. Ничего не понял. Разбираться не стал, ибо столько водки дома уже нету. Скрипт почти работает.
Выводит
Projects/Builder\*.~* Projects/Builder\*.$* Projects/Builder\*.obj Projects/CSharp\*.cache* Projects/CSharp\*.suo
А надо
Projects\Builder\*.~* Projects\Builder\*.$* Projects\Builder\*.obj Projects\CSharp\*.cache* Projects\CSharp\*.suo
По условию задачи
Кроме того, все символы разделителя пути / должны быть преобразованы в \.
А ещё хотелось бы в конце
echo %Result%
в которой бы и был результат преобразований.

Мне необходимо вызывать эту :0 в нескольких местах моего скрипта. Предусмотрено ли что-то вроде ret, чтобы вернуться в место после вызова? Или goto - наше всё?

И ещё. Всё таки для борьбы с пробелами в путях и масках, пусть каждая полная маска будет заключена в кавычки.
То есть
"Projects\Builder\*.~*" "Projects\Builder\*.$*" "Projects\Builder\*.obj" "Projects\CSharp\*.cache*" "Projects\CSharp\*.suo"

Спасибо ещё разок!

Iska
03-01-2016, 22:11
По условию задачи
Кроме того, все символы разделителя пути / должны быть преобразованы в \.
В принципе, пока окончательно не выпилили POSIX — для ОС NT разницы быть не должно. Другое дело, если какие-то утилиты не пользуются функциями ОС, а сами пытаются делать такие операции как разбивка пути на составляющие по символу «/».

Предусмотрено ли что-то вроде ret, чтобы вернуться в место после вызова? Или goto - наше всё? »

call :Метка

exit /b 0

:Метка

exit /b 0
Можно даже значения возвращать в переменную окружения :).

Лео Lапыч
04-01-2016, 10:32
В принципе, пока окончательно не выпилили POSIX — для ОС NT разницы быть не должно. Другое дело, если какие-то утилиты не пользуются функциями ОС, а сами пытаются делать такие операции как разбивка пути на составляющие по символу «/». »
Проверил. Хавает и так, и так. Так что условие Кроме того, все символы разделителя пути / должны быть преобразованы в \. » убираем.

Про exit /b понял. Спасибо!

Можно даже значения возвращать в переменную окружения . »
Это лишнее.

Foreigner
04-01-2016, 13:04
все символы разделителя пути / должны быть преобразованы в \ »

@echo off
setlocal

for /f "tokens=*" %%i in (1.txt) do call:0 %%i
goto:eof

:0

set "a=%~1"
if not "%2"=="" (0>nul set /p="%a:/=\%\%3 " & set p=%a:/=\%) else (0>nul set /p="%p%\%a% ")

Лео Lапыч
04-01-2016, 13:41
Спасибо! А что насчётА ещё хотелось бы в концеecho %Result%в которой бы и был результат преобразований. »иВсё таки для борьбы с пробелами в путях и масках, пусть каждая полная маска будет заключена в кавычки. То есть"Projects\Builder\*.~*" "Projects\Builder\*.$*" "Projects\Builder\*.obj" "Projects\CSharp\*.cache*" "Projecs\CSharp\*.suo"»?

Foreigner
04-01-2016, 15:21
Тогда так:

@echo off
setlocal

for /f "tokens=*" %%i in (1.txt) do call:0 %%i

set "result=%result:/=\%"
echo %result%

goto:eof

:0

if not "%2"=="" (set "p=%~1" && set res="%~1\%3") else (set res="%p%\%1")
if defined result (set result=%result% %res%) else (set result=%res%)

Лео Lапыч
05-01-2016, 22:48
Спасибо всем!
Скрипт автоматизации добавления новых файлов под версионный контроль при фиксации обновлений теперь работает в общем виде и правильно учитывает свойства svn:global-ignores и svn:ignore, чего и требовалось от него добиться.




© OSzone.net 2001-2012