Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » CMD/BAT - [решено] параметры цикла for для построчного анализа текстового файла?!

Ответить
Настройки темы
CMD/BAT - [решено] параметры цикла for для построчного анализа текстового файла?!

Пользователь


Сообщения: 58
Благодарности: 1

Профиль | Отправить PM | Цитировать


Добрый день!
Есть необходимость построчно проанализировать содержимое текстового файла. Никак не могу определиться с синтаксисом.
@for /f "tokens=*" %%A in (c:\text.txt) do @echo %%A – не работает

Отправлено: 15:52, 04-02-2008

 

Пользователь


Сообщения: 79
Благодарности: 2

Профиль | Отправить PM | Цитировать


Iska, подскажите пожалуйста еще пару моментов..

Что такое
Цитата Iska:
^| »
в команде type?


Цитата Burning Hell:
Также я не очень понял, что делают вот эти два параметра после setlocal:
Цитата Iska:
setlocal enableextensions enabledelayedexpansion » »


Еще такой вопрос...Код, который ищет lasr_port и lasr_host я положил в отдельный батник (например, 2.bat) и хочу его вызвать из основного батника (например, 1.bat) с соответствующими параметрами. Пишу так:

Код: Выделить весь код
call 2.bat lasr_port lasr_host
В самом коде 2.bat я планирую вместо lasr_port и lasr_host использовать %1 и %2, но я не знаю как изменить вот эту строчку:

Код: Выделить весь код
) do set s%%i=%%j
***

Можно ли как-то передать найденное значение 2289 (lasr_port) в батник 1.bat?

Последний раз редактировалось Burning Hell, 27-07-2017 в 15:05.


Отправлено: 09:14, 27-07-2017 | #31



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Ветеран


Contributor


Сообщения: 2708
Благодарности: 1684

Профиль | Отправить PM | Цитировать


Burning Hell, 1.bat
Код: Выделить весь код
@Echo Off
cls

Set "FileIn=Z:\Box_In\In File.txt"
Set Arg="lasr_port" "lasr_host"

Call Z:\я170727-2.bat "%FileIn%" "%Arg%"

Echo %lasr_port% 
Echo %lasr_host% 

Pause
GoTo :Eof
я170727-2.bat - придумайте своё имя, пропишите его в предыдущем батнике
Код: Выделить весь код
Set "Key=let"
FOR /F "usebackq tokens=1,2,3 delims==; " %%i IN (`more %1 2^>nul`) DO (
	For %%a In (%~2) Do Call :Ident %%a "%%i" "%%j" "%%k"
)
GoTo :Eof

:Ident
	If /I %2=="%Key%" If /I %1==%3 Set "%~1=%~4"
GoTo :Eof

-------
Даже самая сложная проблема обязательно имеет простое, лёгкое для понимания, неправильное решение. Каждое решение плодит новые проблемы.

Это сообщение посчитали полезным следующие участники:

Отправлено: 20:08, 27-07-2017 | #32


Ветеран


Сообщения: 27449
Благодарности: 8086

Профиль | Отправить PM | Цитировать


Цитата Burning Hell:
Что такое
Цитата Iska:
^| »
в команде type? »
Не так. «|» — символ конвейера между одной командой и другой. В данном случае — между type и findstr.exe. Поскольку команды находятся внутри параметра «команда» цикла разбора for /f, символ конвейера должен быть экранирован символом «^» (иначе он будет применён не к type и findstr.exe, а к for /f).

Цитата Burning Hell:
Код, который ищет lasr_port и lasr_host я положил в отдельный батник (например, 2.bat) »
Будет проще, если Вы вместо вызова отдельного пакетного файла используете процедуры в том же пакетном файле.
Это сообщение посчитали полезным следующие участники:

Отправлено: 20:23, 27-07-2017 | #33


Пользователь


Сообщения: 79
Благодарности: 2

Профиль | Отправить PM | Цитировать


Цитата Iska:
Будет проще, если Вы вместо вызова отдельного пакетного файла используете процедуры в том же пакетном файле. »
Ага, я уже это понял) Поэтому код поиска lasr_port и lasr_host сделал процедурой в том же пакетном файле. И она мне возвращает эти два параметра обратно в батник, чтобы дальше их использовать.

Вопрос у меня вот какой...Можно ли перейти по метке из конца батника в его начало и заново повторить шаги? Код сейчас выглядит примерно так:

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

....код.....
....код.....
<вызов процедуры поиска lasr_port и lasr_host>
<запуск стороннего скрипта, который формирует лог, где предполагается искать ошибку>
....код.....
....код.....

if (здесь идет некая проверка на ошибку){
<запуск стороннего скрипта, если ошибка найдена>
goto start <вернуться в начало, сгенерировать новый лог и еще раз проверить наличие в нем ошибки>
} else {
goto :EOF <закончить работу, если ошибки в последнем сгенерированном логе нет>
}

<процедура поиска lasr_port и lasr_host>
Сейчас скрипт почему-то не переходит по метке start, останавливается внутри if'a. Можно ли как-то решить эту проблему? Может быть, новую сессию открыть?

Последний раз редактировалось Burning Hell, 27-07-2017 в 21:30.


Отправлено: 21:00, 27-07-2017 | #34


Пользователь


Сообщения: 79
Благодарности: 2

Профиль | Отправить PM | Цитировать


Цитата megaloman:
Set "Key=let" FOR /F "usebackq tokens=1,2,3 delims==; " %%i IN (`more %1 2^>nul`) DO ( For %%a In (%~2) Do Call :Ident %%a "%%i" "%%j" "%%k" ) GoTo :Eof :Ident If /I %2=="%Key%" If /I %1==%3 Set "%~1=%~4" GoTo :Eof »
Прокомментируйте пожалуйста ваш код...Много непонятного, я модифицировал вариант Iska (возвращаю параметры в
Код: Выделить весь код
 endlocal & set /a %3=%slasr_port% & %4=%lasr_host%
), но мне интересно, как работает ваш вариант.

Отправлено: 21:17, 27-07-2017 | #35


Ветеран


Сообщения: 27449
Благодарности: 8086

Профиль | Отправить PM | Цитировать


Цитата Burning Hell:
Можно ли перейти по метке из конца батника в его начало и заново повторить шаги? »
Перейти — можно. Вопрос — нужно ли.

Цитата Burning Hell:
Код сейчас выглядит примерно так: »
Показывайте весь код целиком. И желательно не использовать в качестве имён переменных и меток имена внутренних команд и внешних утилит.

Отправлено: 22:32, 27-07-2017 | #36


Пользователь


Сообщения: 79
Благодарности: 2

Профиль | Отправить PM | Цитировать


Вложения
Тип файла: txt check_va.txt
(1.9 Kb, 7 просмотров)

Iska, код приложил.

Смысл работы скрипта в следующем.
Запускается сторонний процесс, который проверяет запущенность некоторого сервера. Далее формируется лог и в случае, если сервер не запущен, в нем будут ошибки. Если ошибки обнаружены, запускается другой сторонний процесс, который уже запускает сервер. После этого я хочу еще раз проверить запустился ли сервер (и если в логе по прежнему есть ошибки, то опять запустить сервер). Поэтому я придумал тему с меткой перехода в начало скрипта (goto start), но почему-то она не срабатывает...

Отправлено: 08:25, 28-07-2017 | #37


Ветеран


Сообщения: 27449
Благодарности: 8086

Профиль | Отправить PM | Цитировать


Цитата Burning Hell:
Iska, код приложил. »
В данном случае лучше делать сие так:

Скрытый текст
Код: Выделить весь код
:start
set day=%date:~0,2%
set month=%date:~3,2%
set year=%date:~6,4%

set /a hour=%time:~0,2%
if %hour% lss 12 (
	set format=AM) else (
	set format=PM)

If %hour% gtr 12 ( set /a hour = %hour% - 12 ) 
If %hour% == 00 ( set hour = 12 )

set /a minute=%time:~3,2%
set /a second=%time:~6,2%

set lasr_log_nm=check_va_lasr_status_%year%-%month%-%day%__%hour%.%minute%.%second% %format%.log

set full_log_path=D:\logs\%lasr_log_nm%

call D:\SAS\sas.exe -sysin D:\codes\check_va_lasr\check_va_lasr_status.sas -log "%full_log_path%"

set port=lasr_port
set host=lasr_host

call :get_params_from_main_config %port% %host% port host

type "%full_log_path%" | >nul 2>&1 findstr.exe /i /l /c:"error" /c:"connection" /c:"lasr" /c:"%port%" /c:"%host%" && set lasrError=true || set lasrError=false

echo lasrError=%lasrError%

if %lasrError%==true (
	call D:\SAS\sas.exe -sysin D:\codes\check_va_lasr\check_lasr_log_and_run.sas -nolog
	echo "Goto second iteration"
	goto :start
) else (
goto :EOF
)

rem =========================================================================
:get_params_from_main_config
@echo off
setlocal enableextensions enabledelayedexpansion

set sSourceFile=D:\codes\common\init_environment.sas

if exist "%sSourceFile%" (
	for /f "usebackq tokens=2,3 delims==; " %%i in (
		`type "%sSourceFile%" ^| findstr.exe /i /r /c:"%%let %1 = [0-9]*;"`
	) do set s%1=%%j

	if defined slasr_port (
		echo [!slasr_port!]
	) else (
		echo Not found [lasr_port]
	)

	for /f "usebackq tokens=2,3 delims==; " %%i in (
		`type "%sSourceFile%" ^| findstr.exe /i /r /c:"%%let %2 = .*;"`
	) do set s%2=%%j

	if defined slasr_host (
		echo [!slasr_host!]
	) else (
		echo Not found [slasr_host]
	)

) else (
	echo Can't find source file [%sSourceFile%].
	exit /b 1
)

endlocal & (set /a %3=%slasr_port% & set %4=%slasr_host%)
exit /b 0
rem =========================================================================

Отправлено: 08:45, 28-07-2017 | #38


Пользователь


Сообщения: 79
Благодарности: 2

Профиль | Отправить PM | Цитировать


Iska, но я не вижу никакой разницы...

Отправлено: 09:37, 28-07-2017 | #39


Ветеран


Contributor


Сообщения: 2708
Благодарности: 1684

Профиль | Отправить PM | Цитировать


Burning Hell,
Цитата Burning Hell:
но я не вижу никакой разницы... »
Я не сильно всматривался, но очевидное отличие в двоеточии goto :start
Вот Ваш код с поправками Iska (я не вчитывался сильно в код и, естественно, не могу его полноценно тестировать) с встроенной моей процедурой
Код: Выделить весь код
@Echo Off
cls

:start
set day=%date:~0,2%
set month=%date:~3,2%
set year=%date:~6,4%

set /a hour=%time:~0,2%
if %hour% lss 12 (
	set format=AM) else (
	set format=PM)

If %hour% gtr 12 ( set /a hour = %hour% - 12 ) 
If %hour% == 00 ( set hour = 12 )

set /a minute=%time:~3,2%
set /a second=%time:~6,2%

set lasr_log_nm=check_va_lasr_status_%year%-%month%-%day%__%hour%.%minute%.%second% %format%.log

set full_log_path=D:\logs\%lasr_log_nm%

call D:\SAS\sas.exe -sysin D:\codes\check_va_lasr\check_va_lasr_status.sas -log "%full_log_path%"

rem set port=lasr_port
rem set host=lasr_host
rem call :get_params_from_main_config %port% %host% port host
rem type "%full_log_path%" | >nul 2>&1 findstr.exe /i /l /c:"error" /c:"connection" /c:"lasr" /c:"%port%" /c:"%host%" && set lasrError=true || set lasrError=false

Call :get_params_from_main_config "D:\codes\common\init_environment.sas" ""lasr_port" "lasr_host""
type "%full_log_path%" | >nul 2>&1 findstr.exe /i /l /c:"error" /c:"connection" /c:"lasr" /c:"%lasr_port%" /c:"%lasr_host%" && set 

lasrError=true || set lasrError=false

echo lasrError=%lasrError%

if %lasrError%==true (
	call D:\SAS\sas.exe -sysin D:\codes\check_va_lasr\check_lasr_log_and_run.sas -nolog
	echo "Goto second iteration"
	goto :start
) else (
	goto :EOF
)

rem =========================================================================

:get_params_from_main_config
	Set "Key=let"
	FOR /F "usebackq tokens=1,2,3 delims==; " %%i IN (`more %1 2^>nul`) DO (
		For %%a In (%~2) Do Call :Ident %%a "%%i" "%%j" "%%k"
	)
GoTo :Eof

:Ident
	If /I %2=="%Key%" If /I %1==%3 Set "%~1=%~4"
GoTo :Eof
Аналогичная процедура от Iska убрана
Попробую в темпе пояснить мою процедуру
Код: Выделить весь код
Call :get_params_from_main_config "D:\codes\common\init_environment.sas" ""lasr_port" "lasr_host""
Вызов Call :get_params_from_main_config "Имя анализируемого файла" "Список искомых параметров"
Список искомых параметров в виде ""Парам1" "Парам2" ..."ПарамN""
После работы процедуры получим переменные, которым присвоены найденные (если они есть) значения
%Парам1% %Парам2% ... %ПарамN%

Под первым For команда (`more %1 2^>nul`) more отображает содержимое файла, имя которого "Имя анализируемого файла" передано в первом аргументе процедуры %1. (смотрите more /? For /?)
2^>nul Подавит вывод сообщения об ошибке, если файл не найден. При этом после Do в For исполняться ничего не будет

В "анализируемом файле" искомые параметры содержатся в строке вида
%let Параметр = значение;
Её надо разобрать на подстроки по разделителям "=; "
1. %let
2. Параметр
3. значение
То есть в For имеем ... tokens=1,2,3 delims==; " и они помещаются в переменных %%i %%j %%k
Возможные неприятности:
Если в Параметре или значении есть пробел - работать будет неправильно из-за использования в качестве разделителя пробела.
Если в значении имеются спецсимволы типа % и др. работать будет неправильно из-за особенностей разбора текста в CMD.
(Описанный баг не баг вовсе а фича
Вложенный в первый For второй For вызавает процедуру :Ident куда передаёт последовательно каждое имя параметра %%a из полученного списка %~2 (передали ""Парам1" "Парам2" ..."ПарамN"" , после ~ имеем "Парам1" "Парам2" ..."ПарамN") и куски строк из файла в аргументах "%%i" "%%j" "%%k"
В процедуре :Ident
%2 -первый кусок строки (если это было %let то при передаче % потерялось)
Итак, если первый кусок строки == "let" (let ранее запомнил в переменную %Key%, стараюсь исходные данные вытянуть за код, чтобы можно было легко изменить при надобности - здесь, похоже, это паранойя), сравнение без учета регистра If /I (смотрим If /?)
If /I %2=="%Key%"
и если переданное имя параметра совпадает с именем параметра в строке If /I %1==%3 (%3 кусок строки с именем параметра, если строка начинается на let)
то переменной с именем нужного параметра %~1 присваиваем найденное значение Set "%~1=%~4"

Лирическое отступление 1. Я стремлюсь операторы типа Set Строка=Значение писать в виде Set "Строка=Значение", что позволяет гарантировать отсутствие невидных пробелов после Значение.
Лирическое отступление 2. Извините за длинноты объяснения, не было времени написать кратко

-------
Даже самая сложная проблема обязательно имеет простое, лёгкое для понимания, неправильное решение. Каждое решение плодит новые проблемы.


Последний раз редактировалось megaloman, 28-07-2017 в 12:14.

Это сообщение посчитали полезным следующие участники:

Отправлено: 11:15, 28-07-2017 | #40



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » CMD/BAT - [решено] параметры цикла for для построчного анализа текстового файла?!

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
CMD/BAT - [решено] Создание текстового файла при условии его отсутствия в папке spilberg Скриптовые языки администрирования Windows 1 12-07-2009 15:58
[решено] Чтение текстового файла с неизвестным именем ZeroCrash AutoIt 4 01-07-2009 19:03
[решено] Заполнение формы на сайте, но с данными из текстового файла ZeroCrash AutoIt 2 24-06-2009 11:04
CMD/BAT - [решено] Как скопировать имя файла из текстового файла в код батника и т.д. Nun-Nun Скриптовые языки администрирования Windows 6 13-05-2009 13:28
CMD/BAT - [решено] вывод текстового файла на экран cmd idsp Скриптовые языки администрирования Windows 6 06-04-2009 07:18




 
Переход