CMD/BAT - поиск и добавление текста в файл с условием

Ответить
Аватара пользователя
Sta1917

CMD/BAT - поиск и добавление текста в файл с условием

Сообщение Sta1917 »

В продолжение
этой
темы

Есть папка с различными файлами, из которой запускается батник, преобразующий кодировку файлов *.txt и *.csv из этой папки и после выполняющий программу конвертируя их в файлы *.kml

Нужно:

1. добавить проверку: если в начале файла есть строка Name,Latitude,Longitude,Description или Name;Latitude;Longitude;Description не добавлять ее в файл. Если нет определить какой разделитель в файле "," или ";" и добавить в начало файла строку Name,Latitude,Longitude,Description с соответстующим разделителем.

2. Проверить код на универсальность, если есть грубые ляпы убрать их.



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



Файлы могут быть следующего вида



Код:

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

Name,Latitude,Longitude,Description
Первая точка,33.32456,65.345678,ВЛ-10/4
Вторая_точка,34.234565,54.5456675,ВЛ-11/1

или



Код:

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

Name;Latitude;Longitude;Description
Первый_знак;33.32456;65.345678;ВЛ-10/4
Второй_знак;34.234565;54.5456675;ВЛ-11/1



Сам батник:



Код:

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

@Echo on
:: =========================================
::      смена кодировки cp1251 на utf-8
:: =========================================
:: создаем папку "utf8"
md utf8
:: перекодируем все файлы с расширением *.txt и *.csv,
:: и кладем их в папку "utf8"
:: в папке с программой должна лежать программа iconv
for %%i in (*.txt *.csv) do ".\iconv\iconv" -t UTF-8 "%%i" > "utf8\%%i"
:: =========================================
::              перевод в *kml
:: =========================================
:: определяем разрядность системы (определяем наличие GPSBabel в установленных программах)
If Defined ProgramFiles(x86) (
	Set gpsbabel="%ProgramFiles(x86)%\GPSBabel\gpsbabel.exe" -w -i unicsv -f
) Else (
	Set gpsbabel="%ProgramFiles%\GPSBabel\gpsbabel.exe" -w -i unicsv -f
)
:: добавляем во все файлы *.txt в папке utf8 строку "Name,Latitude,Longitude,Description"
:: конвертируем и кладем их в папку с исходными
FOR %%i IN (".\utf8\*.txt") DO (
	>"%0.tmp" Echo Name,Latitude,Longitude,Description
	>>"%0.tmp" Type "%%i"
	%gpsbabel% "%0.tmp" -o kml -F "%%~ni.kml" 
)
del "%0.tmp" 2>nul
:: добавляем во все файлы *.csv в папке utf8 строку "Name;Latitude;Longitude;Description"
:: конвертируем и кладем их в папку с исходными
FOR %%i IN (".\utf8\*.csv") DO (
	>"%0.tmp" Echo Name;Latitude;Longitude;Description
	>>"%0.tmp" Type "%%i"
	%gpsbabel% "%0.tmp" -o kml -F "%%~ni.kml" 
)
del "%0.tmp" 2>nul
:: удаляем каталог utf8
rd /s /q "%~dp0\utf8"
exit/b



Пробовал команду:



Код:

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

@type "%~dp0\utf8\test2.txt" | find /i "Name,Latitude,Longitude,Description" >nul && exit
>> "%~dp0\utf8\test2.txt" (echo Name,Latitude,Longitude,Description)

проверку выполняет, и добавляет строку, но только в конец файла.
Аватара пользователя
mwz

Re: CMD/BAT - поиск и добавление текста в файл с условием

Сообщение mwz »

Цитата Sta1917:



добавляет строку, но только в конец файла
CMD/BAT - поиск и добавление текста в файл с условием




Оператор >> именно это и делает: дописывает файл. Если надо вписать в начало — то поменять порядок с учётом того, что в этом случае придётся использовать промежуточный файл, который затем переименовывать: иначе исходный файл затрётся в процессе операции.
Аватара пользователя
megaloman

Re: CMD/BAT - поиск и добавление текста в файл с условием

Сообщение megaloman »

Я слегка запутался в Вашей постановке, что в каком порядке надо делать.

У меня:

1. Файл анализируется на заголовок, если надо, заголовок добавляется. Результат - промежуточный файл.

2. Промежуточный файл перекодируется в UTF-8. Результат - исходный дополненный перекодированный файл.

Перекодировка мной не отлаживалась - нечем и не на чем.

3. Модифицированный исходный конвертируется. Конвертация мной не отлаживалась - нечем и не на чем.

4. Промежуточный файл удаляем.



Код:

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

@Echo Off
Chcp 1251 >nul
:Возможные заголовки
Set "Str1=Name,Latitude,Longitude,Description"
Set "Str2=Name;Latitude;Longitude;Description"
:Возможные разделители
Set "Sep1=,"
Set "Sep2=;"
:Путь к программе gpsbabel
If Exist "%ProgramFiles%\GPSBabel\gpsbabel.exe" Set gpsbabel="%ProgramFiles%\GPSBabel\gpsbabel.exe" -w -i unicsv -f
If Exist "%ProgramFiles(x86)%\GPSBabel\gpsbabel.exe" Set gpsbabel="%ProgramFiles(x86)%\GPSBabel\gpsbabel.exe" -w -i unicsv -f
:Путь к программе Iconv
Set "Iconv=.\iconv\iconv.exe"
:Маски обрабатываемых файлов
Set "Files=*.txt *.csv"
SetLocal EnableExtensions EnableDelayedExpansion
For %%f in (%Files%) Do (
	Call :Separator "%%f"
)
GoTo :Eof
:Separator
FOR /F "usebackq delims=" %%i IN (%1) DO (
	Set /A Str=0
	Set "String=%%i"
        Set "String=!String: =!"
	If /I "!String!"=="%Str1%" Set /A Str=1
	If /I "!String!"=="%Str2%" Set /A Str=2
	If !Str!==0 (
		Set "String=%%i"
		If Not "!String:%Sep1%=!"=="%%i" (>"%~1.tmp" Echo %Str1%)
		If Not "!String:%Sep2%=!"=="%%i" (>"%~1.tmp" Echo %Str2%)
		>>"%~1.tmp" type %1
	) Else (
		>"%~1.tmp" type %1
	)
	"%Iconv%" -t UTF-8 "%~1.tmp" >%1
	%gpsbabel% %1 -o kml -F "%~n1.kml" 
	Del "%~1.tmp" >nul
	GoTo :Eof
)
GoTo :Eof


Цитата:



Проверить код на универсальность, если есть грубые ляпы убрать их.



Теорема: В любой сколь угодно малой программе существует бесконечное кол-во ошибок. Доказывается методом математической индукции из утверждения, что в любой программе имеется хотя бы одна ошибка. Вследствие очевидности доказательство не привожу и предлагаемый процесс предлагаю произвести заказчику Изображение
Аватара пользователя
Iska

Re: CMD/BAT - поиск и добавление текста в файл с условием

Сообщение Iska »

Цитата megaloman:



Теорема: В любой сколь угодно малой программе существует бесконечное кол-во ошибок.
CMD/BAT - поиск и добавление текста в файл с условием




Конечное, коллега, конечное Изображение.
Аватара пользователя
Sta1917

Re: CMD/BAT - поиск и добавление текста в файл с условием

Сообщение Sta1917 »

megaloman, Спасибо, работает. Если сконвертировать его второй раз, получаются крокозябры. Можно чтобы конвертировались промежуточные файлы, либо была проверка на кодировку?



Объясните пожалуйста как добавить другие варианты заголовка и разделителя (табуляции). чтобы код работал?




Цитата megaloman:



:Возможные заголовки

Set "Str1=Name,Latitude,Longitude,Description"

Set "Str2=Name;Latitude;Longitude;Description"



:Возможные разделители

Set "Sep1=,"

Set "Sep2=;"
CMD/BAT - поиск и добавление текста в файл с условием
Аватара пользователя
megaloman

Re: CMD/BAT - поиск и добавление текста в файл с условием

Сообщение megaloman »

Sta1917, У меня есть твёрдое убеждение: исходные файлы, какие бы они ни были, изменять НИЗЗЗЬЯ!! Но Вы моих убеждений, похоже, не разделяете. Изображение

Я бы организовал всё по другому.

1. Новые исходные файлы помещал бы в отдельную папку, например Box_In.

2. Обработанные по полной программе файлы помещал бы тоже в другую папку, например, Box_Out

3. Обработанные исходные перемещал бы в папку, например, Box_Arc



Еще одно моё убеждение, если не продумать организацию системы, то обеспечен постоянный головняк. Когда-то меня натыркивали носом: не бросайся писать код, проработай алгоритм задачи.

Если Вас привлечёт мой подход к реализации, могу изваять вариант.
Аватара пользователя
Iska

Re: CMD/BAT - поиск и добавление текста в файл с условием

Сообщение Iska »

Sta1917,


Здесь вариант, где я постарался по максимуму учесть Ваши пожелания

[spoiler]Код:
[/spoiler]

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

@Echo Off
cls
SetLocal EnableExtensions EnableDelayedExpansion
:Путь к папке, где расположены Box_In, Box_Out, Box_Arc
:::Set "Where=Z:\tralala"
Set "Where="
:Маски файлов
Set "Files=*.txt *.csv"
:Список возможных разделителей
Set "Delim=;,."
:Шаблон заголовка
Set "Str00=Name Latitude Longitude Description"
:Путь к программе gpsbabel
If Exist "%ProgramFiles%\GPSBabel\gpsbabel.exe" Set gpsbabel="%ProgramFiles%\GPSBabel\gpsbabel.exe" -w -i unicsv -f
If Exist "%ProgramFiles(x86)%\GPSBabel\gpsbabel.exe" Set gpsbabel="%ProgramFiles(x86)%\GPSBabel\gpsbabel.exe" -w -i unicsv -f
:Путь к программе Iconv
Set "Iconv=.\iconv\iconv.exe"
:Если батник запускаем с параметрами
If Not "%~1"=="" (
	Echo ----------------------------------------------
	Set "Files=%1" & Echo 1 %1
	If Not "%~2"=="" Set "Files=!Files! %2" & Echo 2 %2
	If Not "%~3"=="" Set "Files=!Files! %3" & Echo 3 %3
	If Not "%~4"=="" Set "Files=!Files! %4" & Echo 4 %4
	If Not "%~5"=="" Set "Files=!Files! %5" & Echo 5 %5
	If Not "%~6"=="" Set "Files=!Files! %6" & Echo 6 %6
	If Not "%~7"=="" Set "Files=!Files! %7" & Echo 7 %7
	If Not "%~8"=="" Set "Files=!Files! %8" & Echo 8 %8
	If Not "%~9"=="" Set "Files=!Files! %9" & Echo 9 %9
	Echo ----------------------------------------------
	Echo Press Enter to continue or Ctrl/C to abort
	Pause >nul
)
:Определение числа возможных разделителей
FOR /L %%d IN (0,1,255) DO (
	Set Dlm=!Delim:~%%d,1!
	If "!Dlm!"=="" GoTo :Cont1
	Set /A Nd=%%d
)
:Cont1
:Делаем рабочие папки если их нет. Если расположение не указано, работаем в папке с батником
If "%Where%"=="" Set "Where=%~dp0" & Set "Where=!Where:~0,-1!"
Md "%Where%\Box_In" 2>nul
Md "%Where%\Box_Out" 2>nul
Md "%Where%\Box_Arc" 2>nul
Pushd "%Where%\Box_In"
Del *.tmp 2>nul
If "%~1"=="" (
	For %%f in (%Files%) Do Call :Text "%Where%\Box_In\%%f"
) Else (
	For %%f in (%Files%) Do Call :Text "%%~f"
)
Pause
Popd
GoTo :Eof
:Separ
: Поиск символа разделителя в строке
Set "Str=%~1"
FOR /L %%s IN (0,1,255) DO (
	Set "Str=%~1"
	Set "Sep=!Str:~%%s,1!"
	If "!Sep!"=="" (
		Set "%~2= "
		Set "%~3=%Str00%"
		GoTo :Eof
	) Else (
		FOR /L %%d IN (0,1,%Nd%) DO (
			Set "%~2=!Delim:~%%d,1!"
			If !%~2!==!Sep! (
				Set "%~3=%Str00: =!Sep!%"
				GoTo :Eof
			)
		)
	)
)
GoTo :Eof
:Text
FOR /F "usebackq delims=" %%i IN (%1) DO (
	Set /A Str=0
	Set "String=%%i"
        Set "String=!String: =!"
	Call :Separ "!String!" "Dlm" "Head"
	If /I Not "!String!"=="!Head!" ( 
		>"%~1.tmp" Echo !Head!
		>>"%~1.tmp" type %1
	) Else (
		>"%~1.tmp" type %1
	)
	"%Iconv%" -t UTF-8 "%~1.tmp" >"%Where%\Box_Out\%~nx1"
	%gpsbabel% "%Where%\Box_Out\%~nx1" -o kml -F "%Where%\Box_Out\%~n1.kml"
rem Имитация программы Iconv  
rem 	Echo "%Iconv%" -t UTF-8 "%~1.tmp" ^>"%Where%\Box_Out\%~nx1"
rem 	Copy "%~1.tmp" "%Where%\Box_Out\%~nx1"
rem Имитация программы gpsbabel
rem 	Echo %gpsbabel% "%Where%\Box_Out\%~nx1" -o kml -F "%Where%\Box_Out\%~n1.kml"
rem 	Copy "%Where%\Box_Out\%~nx1" "%Where%\Box_Out\%~n1.kml"
	Move /Y %1 "%Where%\Box_Arc\" >nul
	Del "%~1.tmp"
	Del "%Where%\Box_Out\%~nx1"
	GoTo :Eof
)
GoTo :Eof








Здесь пояснения к этому варианту

[spoiler]Мысли по организации процесса: В параметре Where должна быть прописана папка, где расположены данные, распределённые по папкам: Box_In, Box_Out, Box_Arc. Если строка пустая, как сейчас в примере, то подразумевается, что эти папки расположены в той же папке, что и батник. Если батник запускается без параметров, то исходные данные берутся из Box_In. Шаблоны обрабатываемых файлов задаются в параметре Files. Если в параметрах имена файлов, то обрабатываются они. В частности, если на рабочем столе создать значок со ссылкой на батник, а затем пометить в папке с данными несколько файлов (не более 9!) и затянуть их на этот значок, то обработаются помеченные файлы. Результаты - в подпапке Box_Out указанной папки в параметре Where. Данные из исходного места перемещаются в Box_Arc. Исходные данные не изменяются.

Разделители: Список разрешенных задаётся строкой параметра Delim. Разделитель из нескольких символов, в частности, запятая с пробелом, точка с запятой с пробелом мной не рассматривались. Ограничение: в данных первого поля не должно быть символов из списка разделителей, иначе возможно неверное определение разделителя полей. Шапка задаётся шаблоном в параметре Str00. В шаблоне наименования полей перечислены через пробел, при отсутствии в файле шапки, для обработки шапка добавляется в промежуточный файл с разделителем, взятым из первой строки, если он содержится в списке возможных разделителей.

У меня нет программ Iconv и gpsbabel, поэтому я использовал для отладки их имитации посредством команды copy. Реально конвертация мной не отлаживалась.[/spoiler]
Ответить

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