Windows Batch For Loop:遇到以下代码问题

时间:2013-02-26 21:32:28

标签: for-loop batch-file

    set checker=0

for %%a in (%namelist%) do (
:startLoop
    findstr "completed" %%a_Logs.txt
    IF ERRORLEVEL 1 (
        IF %checker%==120 (
            set checker=0
            goto endLoop
        )
        set /a checker=%checker%+1
        @ping 127.0.0.1 -n 1 -w 1000 > nul
        findstr "ERROR" %%a_Logs.txt
        IF ERRORLEVEL 1 (
            echo Waiting 1 second before rechecking (Max 2 mins)
            echo time elapsed %checker% seconds
            echo.
            goto startLoop
        )
        findstr "ERROR" %%a_Logs.txt
        IF NOT ERRORLEVEL 1 (
            echo ERROR: %%a Error found
            goto endLoop
        )
    )
    findstr "completed" %%a_Logs.txt
    IF NOT ERRORLEVEL 1 (
        echo %%a completed
    )
:endLoop
)

上面的代码是执行以下操作:

  1. 解析变量名称列表(其中内容以空格分隔)
  2. 检查%% a_Logs.txt文件中是否存在“已完成”
  3. 如果它存在,则迭代结束,如果不存在,则检查同一文件中的字符串“ERROR”
  4. 如果存在ERROR,则输出ERROR MSG并结束迭代
  5. 如果未找到ERROR,请在结束迭代前的下一个120秒内重新检查
  6. 我一直得到以下输出

    FINDSTR:无法打开%a_Logs.txt

2 个答案:

答案 0 :(得分:4)

您正在尝试在FOR循环中GOTO标签 - 这根本不起作用。 FOR循环执行GOTO的那一刻,循环终止,FOR上下文丢失。因此,不再定义%%a FOR变量。 IF语句也会出现类似问题,如(Windows batch) Goto within if block behaves very strangely所述。

当您尝试在设置值的同一括号代码块中展开%checker%时,也会出现问题。该扩展在分析时发生,并且立即解析整个块。因此,您看到的值将始终是输入块之前存在的值。解决方案是启用延迟扩展并使用!checker!代替%checker%

就个人而言,我可能会对您的代码进行重大更改。但我相信以下最小的更改可以使您的代码工作,假设没有其他错误:

  • 启用延迟扩展
  • 将DO循环代码移动到循环外的例程,然后使用%%a作为参数循环调用该例程。 CALL不会破坏循环。
  • 在例程
  • 中替换%1 %%a
  • exit /b替换为goto endLoop。同时将exit /b放在例程的末尾
  • 确保在FOR循环结束时代码不属于例程。我在FOR循环后使用了GOTO
  • !checker!替换为%checker%
  • 编辑 - 必须转发ECHO语句中的)

以下是修改后的代码(未经测试)

setlocal enableDelayedExpansion
set checker=0
for %%a in (%namelist%) do call :startLoop %%a
goto continue

:startLoop
findstr "completed" %1_Logs.txt
IF ERRORLEVEL 1 (
    IF !checker!==120 (
        set checker=0
        exit /b
    )
    set /a checker=checker+1
    @ping 127.0.0.1 -n 1 -w 1000 > nul
    findstr "ERROR" %1_Logs.txt
    IF ERRORLEVEL 1 (
        echo Waiting 1 second before rechecking (Max 2 mins^)
        echo time elapsed !checker! seconds
        echo.
        goto startLoop
    )
    findstr "ERROR" %1_Logs.txt
    IF NOT ERRORLEVEL 1 (
        echo ERROR: %1 Error found
        exit /b
    )
)
findstr "completed" %1_Logs.txt
IF NOT ERRORLEVEL 1 (
    echo %1 completed
)
exit /b

:continue

答案 1 :(得分:2)

我认为你的for循环中的标签搞砸了。我只是尝试将循环的内容移动到一个单独的“子程序”中,这就摆脱了你提到的错误。

试试这个:

set checker=0

for %%a in (foo bar baz) do (
    call :loop %%a
)
goto :eof

:loop
set basename=%1
:startLoop
findstr "completed" %basename%_Logs.txt
IF ERRORLEVEL 1 (
    IF %checker%==120 (
        set checker=0
        goto endLoop
    )
    set /a checker=%checker%+1
    @ping 127.0.0.1 -n 1 -w 1000 > nul
    findstr "ERROR" %basename%_Logs.txt
    IF ERRORLEVEL 1 (
        echo Waiting 1 second before rechecking (Max 2 mins)
        echo time elapsed %checker% seconds
        echo.
        goto startLoop
    )
    findstr "ERROR" %basename%_Logs.txt
    IF NOT ERRORLEVEL 1 (
        echo ERROR: %basename% Error found
        goto endLoop
    )
)
findstr "completed" %basename%_Logs.txt
IF NOT ERRORLEVEL 1 (
    echo %basename% completed
)
:endLoop
goto :eof