CMD/BAT - Задача: парсинг текстового файла

Ответить
Аватара пользователя
Лео Lапыч

CMD/BAT - Задача: парсинг текстового файла

Сообщение Лео Lапыч »

Добрый день, системные администраторы и программисты-разработчики!



Давно хочу решить одну задачку средствами командного интерпретатора 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

Re: CMD/BAT - Задача: парсинг текстового файла

Сообщение Foreigner »

Цитата Лео Lапыч:



На основе файла
CMD/BAT - Задача: парсинг текстового файла






Код:

Код: Выделить всё

@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апыч

Re: CMD/BAT - Задача: парсинг текстового файла

Сообщение Лео Lапыч »

Спасибо, Иностранец. Честно говоря, это читерство какое-то. Ничего не понял. Разбираться не стал, ибо столько водки дома уже нету. Скрипт почти работает.

Выводит



Код:

Код: Выделить всё

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

Re: CMD/BAT - Задача: парсинг текстового файла

Сообщение Iska »

Цитата Лео Lапыч:



По условию задачи


Цитата:



Кроме того, все символы разделителя пути / должны быть преобразованы в \.







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




Цитата Лео Lапыч:



Предусмотрено ли что-то вроде ret, чтобы вернуться в место после вызова? Или goto - наше всё?
CMD/BAT - Задача: парсинг текстового файла







Скрытый текст

[spoiler]Код:
[/spoiler]

Код: Выделить всё

…
call :Метка
…
exit /b 0
…
:Метка
…
exit /b 0







Можно даже значения возвращать в переменную окружения Изображение.
Аватара пользователя
Лео Lапыч

Re: CMD/BAT - Задача: парсинг текстового файла

Сообщение Лео Lапыч »

Цитата Iska:



В принципе, пока окончательно не выпилили POSIX — для ОС NT разницы быть не должно. Другое дело, если какие-то утилиты не пользуются функциями ОС, а сами пытаются делать такие операции как разбивка пути на составляющие по символу «/».
CMD/BAT - Задача: парсинг текстового файла




Проверил. Хавает и так, и так. Так что условие
Цитата Лео Lапыч:



Кроме того, все символы разделителя пути / должны быть преобразованы в \.
CMD/BAT - Задача: парсинг текстового файла




убираем.



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




Цитата Iska:



Можно даже значения возвращать в переменную окружения .
CMD/BAT - Задача: парсинг текстового файла




Это лишнее.
Аватара пользователя
Foreigner

Re: CMD/BAT - Задача: парсинг текстового файла

Сообщение Foreigner »

Цитата Лео Lапыч:



все символы разделителя пути / должны быть преобразованы в \
CMD/BAT - Задача: парсинг текстового файла






Код:

Код: Выделить всё

@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апыч

Re: CMD/BAT - Задача: парсинг текстового файла

Сообщение Лео Lапыч »

Спасибо! А что насчёт
Цитата Лео Lапыч:



А ещё хотелось бы в конце

Код:

Код: Выделить всё

echo %Result%

в которой бы и был результат преобразований.
CMD/BAT - Задача: парсинг текстового файла




и
Цитата Лео Lапыч:



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

Код:

Код: Выделить всё

"Projects\Builder\*.~*" "Projects\Builder\*.$*" "Projects\Builder\*.obj" "Projects\CSharp\*.cache*" "Projecs\CSharp\*.suo"»





?
Аватара пользователя
Foreigner

Re: CMD/BAT - Задача: парсинг текстового файла

Сообщение Foreigner »

Тогда так:



Код:

Код: Выделить всё

@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апыч

Re: CMD/BAT - Задача: парсинг текстового файла

Сообщение Лео Lапыч »

Спасибо всем!

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

Вернуться в «Скриптовые языки администрирования Windows»