wmclaxton
wmclaxton

Reputation: 35

string comparison to break out of loop in batch file

For searches in Windows Registry using batch scripting, I have to loop through a few keys, make a comparison to determine which is the right one, and then update the key.

Iteration in a for loop seems impossible to break out of. I have seen that others are facing similar issues but there does not seem to be a simple solution. Here is a snippet that demonstrates the issue.

@echo off
echo.
echo Diet Favorites

set favorite="bananas"
for %%a in (apples, bananas, chocolates) do call :reviewList %%a
echo.
echo Processing completed.
goto end

:reviewList item
    set foundFavorite="false"
    call :chooseFavorite "%~1"
    if /I "%foundFavorite%"=="true" (
        echo found the favorite - %~1
        exit /b 0
    ) else (
        echo skip %~1
    )
    endlocal & goto :eof

:chooseFavorite item
    if "%~1"==%favorite% set "foundFavorite=true"
    endlocal & goto :eof

:end

chooseFavorite returns the favorite in an environment variable. The output shows that reviewList continues looping after the favorite is identified.

Diet Favorites
skip apples
found the favorite - bananas
skip chocolates

Processing completed.

The comparison is working, but if the exit worked as expected, chocolates diet option should not be listed at all. How do I neatly break out of the loop iteration?

Upvotes: 0

Views: 643

Answers (2)

Magoo
Magoo

Reputation: 79982

@ECHO Off
SETLOCAL
echo.
echo Diet Favorites

set "favorite=bananas"
for %%a in (apples, bananas, chocolates) do call :reviewList %%a&IF DEFINED foundFavorite GOTO foundit
:foundit
echo.
echo Processing completed.
goto end

:reviewList param
set "foundFavorite="
call :chooseFavorite "%~1"
if DEFINED foundFavorite (
 echo found the favorite - %~1
) else (
 echo skip %~1
)
goto :eof

:chooseFavorite param
if "%~1"=="%favorite%" set "foundFavorite=%~1"
goto :eof

:end
GOTO :EOF

Since you don't use any setlocal commands in your posted code, the endlocals are superfluous.

This version sets foundFavorite to empty, and sets it to something (can be anything you like - I just chose the thing that was found, which is often convenient) when a match is found. if defined variable interprets the run-time status of the variable, so it can be used within a for loop.

BTW- try running your original code with echo ON. You would see that your if statements are actually executing if /i ""false""=="true" ...

This is why it's convention on SO to use the set "var=value" syntax for string-assignments. You can then apply quotes as required without worrying about where or whether to apply or remove quotes that may be in variables.

Upvotes: 1

Wisblade
Wisblade

Reputation: 1644

Check the return code of :reviewList in your loop, and break accordingly. You'll need to call properly exit /b 0 on non-breaker calls, and exit /b 1 (or any non-zero value) for breaker calls.

Try that:

@echo off
echo.
echo Diet Favorites

set favorite="bananas"
for %%a in (apples, bananas, chocolates) do (
    call :reviewList %%a || goto :break_loop
)
:break_loop
echo.
echo Processing completed.
goto end

:reviewList item
set foundFavorite="false"
call :chooseFavorite "%~1"
if /I "%foundFavorite%"=="true" (
    echo found the favorite - %~1
    exit /b 1
) else (
    echo skip %~1
)
endlocal
exit /b 0

:chooseFavorite item
if "%~1"==%favorite% set "foundFavorite=true"
endlocal & goto :eof

:end

Output is:

S:\Temp>test

Diet Favorites
skip apples
found the favorite - bananas

Processing completed.

Upvotes: 1

Related Questions