Reputation: 35
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
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 endlocal
s 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
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