2013-03-12 26 views
5

Mam tę pętlę, która powtarza się dla każdej linii w zewnętrznym pliku. Chciałbym poprosić użytkownika o wybór w każdym przebiegu, ale to nie działa. Sądzę, że problem polega na tym, że polecenie GOTO w jakiś sposób przerywa pętlę. Jakieś przemyślenia na ten temat?WYBÓR w pętli FOR - Windows Batch

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 
) 

Odpowiedz

8

Twoje rozliczenie jest poprawne. goto w ciągu pętli przerwie pętlę. Aby obejść to, należy zamiast tego użyć call. Jednak pierwszym problemem z twoim skryptem jest potrzeba opóźnionego rozszerzenia dla zmiennej ERRORLEVEL. Kiedykolwiek rozwijasz zmienne, które są ustawione w zakresie nawiasów, użyj opóźnionego rozwinięcia, aby uzyskać najnowszą wartość.

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. gotonie może być używany w for pętli.
  2. Zmienne ustawione w nawiasach wymagają opóźnionego rozwinięcia w celu pobrania nowej wartości. ! zamiast %. W przeciwnym razie zostanie użyta wartość zmiennej przed zakresem nawiasów.
+0

genialny, dziękuję! – Ozrix

+0

+1, ale wysłałem też alternatywną odpowiedź. – jimhark

5

@ Odpowiedź Metzgera była dobrym początkiem (przegłosowałem go), ale znalazłem kilka problemów z tym. Na koniec wolę umieścić kod w linii i ominąć numer CALLs. Oto mój kod test, aby pokazać jak to się robi:

@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 
    ) 
) 

Testowałem @ odpowiedź Metzgera w systemie Windows XP i stwierdzili, że następujące zagadnienia:

  • Podprogramy brakujących GOTO :EOF (już na stałe)
  • W systemie Windows XP w podprogramów %%i jest ustawiona
  • (Potential bug) Jeśli odinstalować ustawia ERRORLEVEL, SKIP można nazwać

Ten kod testu rozwiązuje problemy:

@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 
+0

+1 To są dobre punkty do zapamiętania. ** ':)' ** Zwłaszcza, że ​​ERRORLEVEL jest prawdopodobnie ustawiony w UNINSTALL. Zastanowiłem się nad podaniem parametru %% i jako parametru, ale uznałem, że nie było to konieczne (działa na 7 i 8). –

+0

przegłosowano, dzięki – Ozrix

1

Struktura ta pozwala uniknąć stosowania 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 
Powiązane problemy