#batch-file #for-loop #echo #findstr
#пакетный файл #for-цикл #echo #findstr
Вопрос:
У меня есть несколько строк, которые поступают из reg-запроса внутри цикла for. Я хочу проверить для каждого из них, есть ли в нем определенные слова, и выполнить действия, если они есть. Мой код такой:
for /l %%g in (0 1 3) do (
echo HOME%%g
for /f "tokens=1,2,3*" %%h in ('reg query \%%cHKLMSOFTWAREORACLEHOME%%g /v ORACLE_HOME') do (
echo HOME%%g
echo %%j
echo %%j | findstr /I /R /C:"806"
if %ERRORLEVEL% equ 0 (
echo YES
) else (
echo NO
)
echo %%j | findstr /C:".isuites."
if %ERRORLEVEL% equ 0 (
echo YES
) else (
echo NO
)
echo %%j | findstr /I ora90
if errorlevel 0 (
echo YES
) else (
echo NO
)
echo %%j | findstr /I forms10
if errorlevel 0 (
echo YES
) else (
echo NO
)
)
)
Проблема в том, что is не проверяет строку, как видно на выходе
HOME0
HOME0
ECHO is off.
YES
YES
YES
YES
HOME0
d:oracle806
d:oracle806
YES
YES
YES
YES
HOME1
HOME1
ECHO is off.
YES
YES
YES
YES
HOME1
d:oracleiSuites
YES
YES
YES
YES
HOME2
HOME2
ECHO is off.
YES
YES
YES
YES
HOME2
d:oracleora90
YES
YES
d:oracleora90
YES
YES
HOME3
HOME3
ECHO is off.
YES
YES
YES
YES
HOME3
D:oracleforms10g
YES
YES
YES
D:oracleforms10g
YES
Комментарии:
1. «ECHO %%J» — это ORACLE_HOME. В этом случае он возвращает 4 разных ORACLE_HOMEs.
2. Эта информация нам не поможет, поскольку мы не знаем, какие переменные h , i и j получаются при разборе выходных данных команды
reg query
с помощьюtokens=1,2,3*
.ECHO is off.
в выходных данных указано, что переменная j является пустой строкой и, следовательно,echo %%j
находится толькоecho
при выполнении, что приводит к печати статуса echo в окне консоли.3. Строки, которые должны возвращаться в запросе req, следующие: d:oracle806 d:oracleisuites d:oracleora90 d:oracleforms10g Переменная %%G — это счетчик, который возвращает HOME0, HOME1, HOME2 и HOME3 Итак, у вас должно быть, как и пример: HOME0 d:oracle806 Дело в том, что для каждого ДОМА … 0, 1, 2, 3 … тест, в котором на самом деле есть home … 806, isuites, forms10g или ora90, надеюсь, это поможет
Ответ №1:
В вашем коде необходимы некоторые исправления
Измените for %%h
на
for /f "tokens=1,2,*" %%h in ('reg query \%%cHKLMSOFTWAREORACLEHOME%%g /v ORACLE_HOME ^| find "REG_SZ" ') do (
Таким образом, ORACLE_HOME
имя ключа будет в %%h
, REG_SZ
тип в %%i
и папка в %%j
(я полагаю, это то, что вы имели в виду)
После этого следующей проблемой являются errorlevel
проверки
Когда блок кода (код внутри круглых скобок) анализируется, все чтения переменной заменяются значением внутри переменной перед началом выполнения блока. Итак, если вы используете %errorlevel%
внутри себя блок кода, поскольку эта переменная read была заменена значением переменной перед началом выполнения, вы не увидите реального значения.
Вы можете использовать отложенное расширение (включить setlocal enabledelayedexpansion
в начале пакетного файла) и изменить синтаксис с %errorlevel%
на !errorlevel!
, чтобы указать анализатору, что чтение переменной должно быть отложено до момента выполнения команды.
Или вы можете использовать if errorlevel n ...
синтаксис. В этом случае вы должны помнить, что условие будет истинным для любого errorlevel
значения, большего или равного указанному значению.
То есть, если errorlevel
равно 1, оба if errorlevel 1
и if errorlevel 0
будут истинными. По этой причине правильным способом проверки уровня ошибки является переход от больших значений к меньшим
echo %%j | findstr .....
if errorlevel 1 (
...
) else (
...
)
Итак, ваш код должен быть чем-то вроде
....
....
for /l %%g in (0 1 3) do (
echo Testing HOME%%g
echo ---------------------------------
for /f "tokens=1,2,*" %%h in (
'reg query \%%cHKLMSOFTWAREORACLEHOME%%g /v ORACLE_HOME 2^>nul ^| find "REG_SZ" '
) do (
echo %%j | findstr /L /C:"806"
if errorlevel 1 (
echo NO
) else (
echo YES
)
echo %%j | findstr /C:".isuites."
if errorlevel 1 (
echo NO
) else (
echo YES
)
echo %%j | findstr /I /C:"ora90"
if errorlevel 1 (
echo NO
) else (
echo YES
)
echo %%j | findstr /I /C:"forms10"
if errorlevel 1 (
echo NO
) else (
echo YES
)
)
)
)
отредактировано для адаптации к комментариям
Некоторые из HOMEn
не будут повторены, если они не существуют в реестре. Чтобы «решить» это, вывод ошибки из req query
включается в анализируемые данные и проверяется, найдена ли строка ERROR:
.
for /l %%g in (0 1 3) do (
echo Testing HOME%%g
echo ---------------------------------
for /f "tokens=1,2,*" %%h in (
'reg query \%%cHKLMSOFTWAREORACLEHOME%%g /v ORACLE_HOME 2^>^amp;1 ^| findstr /L /C:"REG_SZ" /C:"REG_EXPAND_SZ" /C:"ERROR:" '
) do (
for %%z in ("806" ".isuites." "ora90" "forms10") do (
(if "%%h"=="ERROR:" (echo() else (echo %%j)) | findstr /i /c:"%%~z"
if errorlevel 1 (
echo NO
) else (
echo YES
)
)
)
)
)
Комментарии:
1. Привет, спасибо за ваш вклад. %%j уже возвращает папку, что фактически и было задумано. Что касается уровня ошибки, я изменил ваше предложение, и результат тот же… Я всегда получаю YESs, когда он должен возвращать только одно «ДА» и 3 «Нет» для каждого из ORACLE_HOMEs
2. Если я изменю %ERRORLEVEL% на !errorlevel! с deplyedexpansion он просто говорит, что это было неожиданно в это время и не будет выполняться
3. @PedroSales, я включил измененную копию вашего кода.
4. Если позволите, единственная проблема с этим новым кодом заключается в том, что HOME0 не выводится ….
5. Еще раз спасибо за ваше обновление. HOME0 все еще не тестируется, и это должно быть потому, что он существует, d:oracle806 и ошибка не возвращается