PDA

Показать полную графическую версию : [решено] параметры цикла for для построчного анализа текстового файла?!


Страниц : 1 2 [3]

Burning Hell
28-07-2017, 14:32
Я не сильно всматривался, но очевидное отличие в двоеточии goto :start »
Двоеточие - оно и у меня в файле есть и в коде Iska...Или я вас не так понял.


megaloman, спасибо за подробное объяснение вашего кода! Я в CMD новичок, прогую на других языках, CMD дается тяжелее из-за сильных различий по отношению к другим языкам.

Несколько вопросов по поводу вашего кода.

Поясните пожалуйста, для чего нужно два знака процента у переменных: "%%i" "%%j" "%%k" » Можно же писать и так: "%i%" "%j%" "%k%"? В чем разница ?

Не понял для чего нужна тильда: "%~1=%~4" » ?

И зачем нужно %%a » при вызове процедуры Ident ?

Iska
28-07-2017, 14:41
Поясните пожалуйста, для чего нужно два знака процента у переменных:
Цитата 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 Там ближе к концу это описано.
Смысл совпадает как для переменных цикла, так и для аргументов подпрограммы

Iska
28-07-2017, 15:40
Для понимания проделайте код:
… 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" выводилось только при нахождении всех трех слов (логическое "И")?

Iska
07-08-2017, 16:07
Сейчас тестировал этот момент и обнаружил, что даже если в целевом файле найдено хотя бы одно слово из трех (например, первое), то уже выводится "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
07-08-2017, 21:22
Iska, А зачем при поиске нужен конвейер »
Сила привычки. В данном случае несущественно, но вообще find.exe в этом случае «гадит» в stdout именем файла, предварённым символами «-».




© OSzone.net 2001-2012