Показать полную графическую версию : [решено] параметры цикла for для построчного анализа текстового файла?!
Burning Hell
28-07-2017, 14:32
Я не сильно всматривался, но очевидное отличие в двоеточии goto :start »
Двоеточие - оно и у меня в файле есть и в коде Iska...Или я вас не так понял.
megaloman, спасибо за подробное объяснение вашего кода! Я в CMD новичок, прогую на других языках, CMD дается тяжелее из-за сильных различий по отношению к другим языкам.
Несколько вопросов по поводу вашего кода.
Поясните пожалуйста, для чего нужно два знака процента у переменных: "%%i" "%%j" "%%k" » Можно же писать и так: "%i%" "%j%" "%k%"? В чем разница ?
Не понял для чего нужна тильда: "%~1=%~4" » ?
И зачем нужно %%a » при вызове процедуры Ident ?
Поясните пожалуйста, для чего нужно два знака процента у переменных:
Цитата megaloman:
"%%i" "%%j" "%%k" »
Можно же писать и так: "%i%" "%j%" "%k%"? В чем разница ? »
Нельзя. %%i и т.д. — специальные переменные цикла разбора. Два символа % нужно из-за того, что цикл разбора используется внутри пакетного файла, а не непосредственно в командной строке. В отличие от них, %i% и т.д. — обычные переменные окружения.
Не понял для чего нужна тильда:
Цитата megaloman:
"%~1=%~4" »
? »
Для того, чтобы убрать кавычки (буде таковые) в значениях переменных %1 и %4.
megaloman
28-07-2017, 15:21
И зачем нужно %%a при вызове процедуры Ident ? »
Для понимания проделайте код: @Echo Off
cls
Call :get_params_from_main_config "D:\codes\common\init_environment.sas" ""lasr_port" "lasr_host""
pause
GoTo :Eof
:get_params_from_main_config
Echo %1
Echo %2
Echo:
Echo %~2
For %%a In (%~2) Do Echo Call :Ident %%a "%%i" "%%j" "%%k"
GoTo :Eof
В цикле последовательно из списка, взятого из переданного аргумента %~2 подпрограммы в подпрограмму :Ident для каждой строки для сравнения передаём имя искомого параметра. Проделайте команду For /? >D:\_For.help и почитайте файл D:\_For.help Там ближе к концу это описано.
Смысл совпадает как для переменных цикла, так и для аргументов подпрограммы
Для понимания проделайте код:
… Call :Ident … »
:Ident по пути потерялась?
megaloman
28-07-2017, 15:52
Iska, там эхо для иллюстрации работы For, реального вызова :Ident нет
Burning Hell
28-07-2017, 16:13
Если в значении имеются спецсимволы типа % и др. работать будет неправильно из-за особенностей разбора текста в CMD. »
Еще такой вопрос. В значение хоста есть дефис и точки. Будут ли с ними проблемы?
megaloman
28-07-2017, 18:17
Burning Hell, %global vaRepLib vaRepLib lasr_port lasr_engine lasr_tag lasr_host lasr_signer lasr_options metaport metaprotocol metarepository lasr_sig_files_path;
%let vaRepLib = lasrlib;
%let lasr_port = 2289;
%let lasr_engine = sasiola;
%let lasr_tag = va_pub;
%let lasr_host = sas-vaar.dev.rnw;
%let lasr_signer = %str("http://sas-metadata.dev.rnw:85/SASLASRAuthorization");
%let lasr_options = %str(tag=&lasr_tag port=&lasr_port host="&lasr_host" signer=&lasr_signer);@Echo Off
cls
Set /A Iter=0
:Begin
If %Errorlevel%==2 GoTo :Eof
Set /A Iter+=1
Echo +++ Begin %Iter% Iteration
Set "DD=%Date:~0,2%"
set "MM=%Date:~3,2%"
set "YYYY=%Date:~6,4%"
Set "HH=%Time: =0%"
Set "MN=%HH:~3,2%"
Set "SS=%HH:~6,2%"
Set "HH=%HH:~0,2%"
Set "FMT=AM"
If %HH% GTR 12 (
Set "FMT=PM"
Set /A HH=%HH%-12+100
)
If %HH% GTR 100 Set "HH=%HH:~1,2%"
If %HH%==00 Set "HH=12"
Set "LogFile=D:\logs\check_va_lasr_status_%YYYY%-%MM%-%DD%__%HH%.%MN%.%SS% %FMT%.log"
Call "D:\SAS\sas.exe" -sysin "D:\codes\check_va_lasr\check_va_lasr_status.sas" -log "%LogFile%"
Call :get_params_from_main_config "D:\codes\common\init_environment.sas" ""lasr_port" "lasr_host""
>nul 2>&1 findstr.exe /i /l /c:"error" /c:"connection" /c:"lasr" /c:"%lasr_port%" /c:"%lasr_host%" "%LogFile%" && (
Call "D:\SAS\sas.exe" -sysin "D:\codes\check_va_lasr\check_lasr_log_and_run.sas" -nolog
CHOICE /C YN /T 15 /D N /M "Iteration %Iter% finished with Errors. Y - Continue, N - Cancel."
Echo:
GoTo :Begin
) || (
Echo +++ Iteration %Iter% finished successfully
GoTo :Eof
)
GoTo :Eof
: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
Burning Hell
07-08-2017, 15:09
Или ещё.
Код:
type "%full_log_path%" | >nul 2>&1 findstr.exe /i /l /c:"word1" /c:"word2" /c:"word3" && echo Found || echo Not found »
Сейчас тестировал этот момент и обнаружил, что даже если в целевом файле найдено хотя бы одно слово из трех (например, первое), то уже выводится "Found". Как сделать, чтобы "Found" выводилось только при нахождении всех трех слов (логическое "И")?
Сейчас тестировал этот момент и обнаружил, что даже если в целевом файле найдено хотя бы одно слово из трех (например, первое), то уже выводится "Found". »
Именно так.
Как сделать, чтобы "Found" выводилось только при нахождении всех трех слов (логическое "И")? »
Можно, конечно, сделать и одним findstr, но уж больно монструозно будет, поскольку потребует 6 (3! = 6) перестановок:
type "%full_log_path%" | >nul 2>&1 findstr.exe /i /r /c:"word1.*word2.*word3" /c:"word1.*word3.*word2" /c:"word2.*word1.*word3" /c:"word2.*word3.*word1" /c:"word3.*word1.*word2" /c:"word3.*word2.*word1" && echo Found || echo Not found
А для 4 слов понадобится уже 4! = 24 перестановки, что не есть хорошо и правильно.
Посему проще будет так:
set /a bFound = 0
type "%full_log_path%" | >nul 2>&1 find.exe /i "word1" && set /a bFound = 1
type "%full_log_path%" | >nul 2>&1 find.exe /i "word2" && set /a bFound = 1
type "%full_log_path%" | >nul 2>&1 find.exe /i "word3" && set /a bFound = 1
if "%bFound%" equ "1" (
echo Found
) else (
echo Not found
)
Можно усложнить, убрав лишние проходы:
set /a bFound = 0
type "%full_log_path%" | >nul 2>&1 find.exe /i "word1" && (
type "%full_log_path%" | >nul 2>&1 find.exe /i "word2" && (
type "%full_log_path%" | >nul 2>&1 find.exe /i "word3" && set /a bFound = 1
)
)
if "%bFound%" equ "1" (
echo Found
) else (
echo Not found
)
Ни то, ни другое не проверялось (оставляю это Вам).
P.S. Интересно, то будет в этом случае:
type "%full_log_path%" | >nul 2>&1 findstr.exe /i /v /l /c:"word1" /c:"word2" /c:"word3" && echo Not found || echo Found
Опять же, не проверялось.
Burning Hell
07-08-2017, 16:12
Iska, спасибо...Была у меня мысль, что придется для каждого слова отдельный findstr писать, но думал, что можно как-то соптимизировать. Ладно, это не критично. Еще раз спасибо.
megaloman
07-08-2017, 21:06
Burning Hell, @Echo Off
cls
Set /A Iter=0
:Begin
If %Errorlevel%==2 GoTo :Eof
Set /A Iter+=1
Echo +++ Begin %Iter% Iteration
Call :StrDate "DateTime"
Set "LogFile=D:\logs\check_va_lasr_status_%DateTime%.log"
Call "D:\SAS\sas.exe" -sysin "D:\codes\check_va_lasr\check_va_lasr_status.sas" -log "%LogFile%"
Call :get_params_from_main_config "D:\codes\common\init_environment.sas" ""lasr_port" "lasr_host""
Call :IfAND "%LogFile%" "error" "connection" "lasr" "%lasr_port%" "%lasr_host%" && (
Call "D:\SAS\sas.exe" -sysin "D:\codes\check_va_lasr\check_lasr_log_and_run.sas" -nolog
CHOICE /C YN /T 15 /D N /M "Iteration %Iter% finished with Errors. Y - Continue, N - Cancel."
Echo:
GoTo :Begin
) || (
Echo +++ Iteration %Iter% finished successfully
GoTo :Eof
)
GoTo :Eof
: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
:IfAND
>nul 2>&1 findstr.exe /i /l /C:%2 %1 || Exit /B 1
Shift /2
If Not "%2"=="" GoTo :IfAND
Exit /B 0
:StrDate
FOR /F "tokens=2 delims==." %%d in ('WMIC OS GET LOCALDATETIME /VALUE') DO SET @Tdate=%%d
Set "@Ttime=1%@Tdate:~8,6%"
Set "@Tdate=%@Tdate:~0,4%-%@Tdate:~4,2%-%@Tdate:~6,2%"
If %@Ttime% LSS 1120000 (Set "%~1=%@Tdate%__%@Ttime:~1,2%.%@Ttime:~3,2%.%@Ttime:~1,2% AM" &GoTo :Eof)
Set /A @Ttime=%@Ttime%-120000
Set "%~1=%@Tdate%__%@Ttime:~1,2%.%@Ttime:~3,2%.%@Ttime:~1,2% PM"
GoTo :Eofгде ввызове подпрограммы Call :IfAND "%LogFile%" "error" "connection" "lasr" "%lasr_port%" "%lasr_host%" - в первом аргументе - имя файла "%LogFile%",
- в остальных аргументах -искомые слова в кавычках. Здесь пять слов. Уберите лишние.
Процедура возвращает %ErrorLevel%==0 если все слова найдены, иначе %ErrorLevel%==1
Iska, А зачем при поиске нужен конвейер
type "%full_log_path%" | >nul 2>&1 find.exe
type "%full_log_path%" | >nul 2>&1 findstr.exeКогда можно напрямую сослаться на файл "%full_log_path%" в find.exe и findstr.exe ?
Iska, А зачем при поиске нужен конвейер »
Сила привычки. В данном случае несущественно, но вообще find.exe в этом случае «гадит» в stdout именем файла, предварённым символами «-».
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.