Войти

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


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

Iska
26-07-2017, 15:49
У меня есть скрипт (код), »
Покажите образец этого «скрипт (код)».

в котором я хочу найти несколько фраз »
Каких? Перечислите.

и вырезать из этих фраз подстроки. »
По какому принципу подстроки должны определяться внутри строки?

Burning Hell
26-07-2017, 15:56
Покажите образец этого «скрипт (код)». »

Скрипт написан на SAS/Macro. Выглядит примерно так:

%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);


Каких? Перечислите. »
Хотелось бы найти строчку с переменной lasr_port и вырезать в переменную число после знака "=". То же самое с переменной
lasr_host.

Iska
26-07-2017, 16:22
Скрипт написан на SAS/Macro. Выглядит примерно так: »
На всякий случай — кодировка его какая?

Хотелось бы найти строчку с переменной lasr_port и вырезать в переменную число после знака "=". То же самое с переменной
lasr_host. »
@echo off
setlocal enableextensions enabledelayedexpansion

set sSourceFile=C:\Мои проекты\0102\0001.txt

if exist "%sSourceFile%" (
for /f "usebackq tokens=2,3 delims==; " %%i in (
`type "%sSourceFile%" ^| findstr.exe /i /r /c:"%%let lasr_port = [0-9]*;"`
) do set s%%i=%%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 lasr_host = .*;"`
) do set s%%i=%%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
exit /b 0

Burning Hell
26-07-2017, 16:28
На всякий случай — кодировка его какая? »
UTF-8 w/o BOM

Iska
26-07-2017, 16:41
UTF-8 w/o BOM »
Тогда сойдёт (пока кириллицу из файла получать не понадобится :)).

Burning Hell
26-07-2017, 16:45
Iska, возникло несколько вопросов.

Что означает вот этот оператор
set s%%i=%%j » ?

Для чего нужны квадратные скобки [!slasr_host!] » и что такое slasr_port? Откуда он берется?

Также я не очень понял, что делают вот эти два параметра после setlocal:

setlocal enableextensions enabledelayedexpansion »

Тогда сойдёт (пока кириллицу из файла получать не понадобится ). »

Там кириллицы по определению не может быть, это же код, исполняемый файл)

Iska
26-07-2017, 17:05
Что означает вот этот оператор »
что такое slasr_port? Откуда он берется? »
Строка в файле выглядит как:
%let lasr_port = 2289;
Посредством цикла разбора for /f "usebackq tokens=2,3 delims==; " мы разбиваем её на составляющие:
%let lasr_port = 2289;
и выбираем второй и третий токены в %%i и %%j соответственно. Таким образом строка:
set s%%i=%%j
выполняется как:
set slasr_port=2289
s я просто добавляю как префикс для получаемой переменной окружения. Привычка.

Для чего нужны квадратные скобки »
Для правильного восприятия. Например, чтобы визуально видеть обрамляющие пробелы, которые без ограничителей [] будут не видны.

Burning Hell
26-07-2017, 17:16
Iska, правильно я понял, что
.* »

последовательность любых символов ?

Iska
26-07-2017, 17:22
Burning Hell, правильно. В том числе и пустая последовательность. К сожалению, реализация регулярок у findstr.exe весьма куцая.

megaloman
26-07-2017, 17:22
@Echo Off
cls

Set "FileIn=Z:\Box_In\In File.txt"
Set "Key=let"

FOR /F "usebackq tokens=1,2,3 delims==; " %%i IN (`more "%FileIn%" 2^>nul`) DO (
Call :Ident "lasr_port" "%%i" "%%j" "%%k"
Call :Ident "lasr_host" "%%i" "%%j" "%%k"

rem Остальные три строки вставил как пример возможности
Call :Ident "vaRepLib" "%%i" "%%j" "%%k"
Call :Ident "lasr_engine" "%%i" "%%j" "%%k"
Call :Ident "lasr_tag" "%%i" "%%j" "%%k"
)
Echo %lasr_port%
Echo %lasr_host%

Echo %vaRepLib%
Echo %lasr_engine%
Echo %lasr_tag%

pause
GoTo :Eof

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

Burning Hell
27-07-2017, 09:14
Iska, подскажите пожалуйста еще пару моментов..

Что такое ^| » в команде type?


Также я не очень понял, что делают вот эти два параметра после 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?

megaloman
27-07-2017, 20:08
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

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

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

Burning Hell
27-07-2017, 21:00
Будет проще, если Вы вместо вызова отдельного пакетного файла используете процедуры в том же пакетном файле. »

Ага, я уже это понял) Поэтому код поиска 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:17
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%), но мне интересно, как работает ваш вариант.

Iska
27-07-2017, 22:32
Можно ли перейти по метке из конца батника в его начало и заново повторить шаги? »
Перейти — можно. Вопрос — нужно ли.

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

Burning Hell
28-07-2017, 08:25
Iska, код приложил.

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

Iska
28-07-2017, 08:45
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 =========================================================================

Burning Hell
28-07-2017, 09:37
Iska, но я не вижу никакой разницы...

megaloman
28-07-2017, 11:15
Burning Hell, но я не вижу никакой разницы... » Я не сильно всматривался, но очевидное отличие в двоеточии goto :start @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. Извините за длинноты объяснения, не было времени написать кратко




© OSzone.net 2001-2012