пакетный файл с echo findstr, не работающий внутри цикла for

#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 и ошибка не возвращается