5

我有这个循环,它对外部文件中的每一行重复。我想在每次通过时提示用户进行选择,尽管这不起作用。我认为问题在于 GOTO 命令以某种方式打破了循环。对此有什么想法吗?

FOR /F %%i IN (%WORKDIR%\grunt-packages.ini) DO (
    CHOICE /C AN /M "Odinstalovat plugin"
    IF %ERRORLEVEL%==1 GOTO UNINSTALL
    IF %ERRORLEVEL%==2 GOTO SKIP

    :UNINSTALL
        ECHO Odstranuji %%i 
        CALL npm uninstall %%i

    :SKIP
        ECHO Preskakuji %%i
)
4

3 回答 3

8

你的推算是正确的。 goto在 for 循环内将停止循环。解决此问题的方法是call改用。但是,您的脚本的第一个问题是需要延迟扩展ERRORLEVEL变量。每当扩展在括号范围内设置的变量时,使用延迟扩展来获取最新值。

SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
FOR /F %%i IN (%WORKDIR%\grunt-packages.ini) DO (
    CHOICE /C AN /M "Odinstalovat plugin"
    IF !ERRORLEVEL!==1 CALL :UNINSTALL
    IF !ERRORLEVEL!==2 CALL :SKIP
)
ENDLOCAL
GOTO :EOF

:UNINSTALL
    ECHO Odstranuji %%i 
    CALL npm uninstall %%i
    GOTO :EOF

:SKIP
    ECHO Preskakuji %%i
    GOTO :EOF
  1. goto 不能for循环中使用。
  2. 括号内设置的变量需要延迟扩展以检索新值。!而不是%. 否则,将使用括号范围之前的变量值。
于 2013-03-12T12:51:10.490 回答
6

@Metzger 的回答是一个好的开始(我投了赞成票),但我发现它存在一些问题。最后,我更喜欢将代码内联并避免CALLs. 这是我的测试代码以显示它是如何完成的:

@echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
FOR %%i IN (A B C D) DO (
    CHOICE /C AN /M "Uninstall plugin %%i"
    IF !ERRORLEVEL!==1 (
        ECHO Uninstall %%i
    ) ELSE IF !ERRORLEVEL!==2 (
        ECHO Skip %%i
    )
)

我在 Windows XP 上测试了@Metzger 的答案,发现了以下问题:

  • 缺少子程序GOTO :EOF(已修复)
  • 在 Windows XP 上,%%i未设置子程序
  • (潜在错误)如果卸载设置ERRORLEVEL,可能会调用 SKIP

此测试代码解决了以下问题:

@echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
FOR %%i IN (A B C D) DO (
    CHOICE /C AN /M "Uninstall plugin %%i"
    SET OERRORLEVEL=!ERRORLEVEL!
    IF !ERRORLEVEL!==1 CALL :UNINSTALL %%i
    IF !OERRORLEVEL!==2 CALL :SKIP %%i
)
ENDLOCAL
GOTO :EOF

:UNINSTALL
    ECHO Uninstall %1
    GOTO :EOF

:SKIP
    ECHO Skip %1
    GOTO :EOF
于 2013-03-12T13:35:29.933 回答
1

这种结构避免了使用 DELAYEDEXPANSION

@ECHO OFF
SETLOCAL
FOR %%i IN (A B C D) DO (
SET destcall=BADCHOICE
choice /c QJ /M "%%i - choose Q or J"
IF ERRORLEVEL 1 SET destcall=CHOSEQ
IF ERRORLEVEL 2 SET destcall=CHOSEJ
CALL CALL :%%destcall%%
)
GOTO :eof

:badchoice
ECHO bad choice
GOTO :eof

:choseq
ECHO You chose Q
GOTO :eof

:chosej
ECHO You chose J
GOTO :eof
于 2013-03-12T14:20:00.130 回答