Page 1 of 3

Is it possible to break loop?

Posted: 25 Jun 2012 04:01
by doscode
I tried to break loop. Now it seems it does not work.

The script is long, so just shorted:

Code: Select all

FOR /F "tokens=1-20 delims=<>" %%A IN ('somefile.txt') DO (
FOR %%Z in ( "%%A", "%%B", "%%C", "%%D", "%%E", "%%F", "%%G", "%%H", "%%I",  "%%J", "%%K",  "%%L", "%%M", "%%N", "%%O", "%%P", "%%Q") DO (
  if !break! EQU 1 (
  echo this is error
  pause
  )
   SET /A cnt=!cnt!+1
   if !cnt! LSS 4 (
          SET IP=!IP!!legalNumber!.
    ) else (
          SET IP=!IP!!legalNumber!
          SET /A cnt=0
          SET /A break=1
          break;
    )
    echo /!cnt!/!IP!
 
REM Endof For %%Z
)
)

As I added

Code: Select all

  if !break! EQU 1 (
  echo this is error
  pause
  )

I have found that the loop continues even it was breaked. If I would use exit /b instead, the script is finished.

Re: Is it possible to break loop?

Posted: 25 Jun 2012 05:48
by jeb
:roll: Did you read the help for
break;


Sometimes it's useful to read the help or ask google :!:

Re: Is it possible to break loop?

Posted: 25 Jun 2012 06:06
by doscode
jeb wrote::roll: Did you read the help for
break;


Sometimes it's useful to read the help or ask google :!:


Yes I did :!:

Break /? Is very curt

I think I have two options. Either to use inner condition (cycles would not be skipped) or to move the inner code to separated subroutine and to call this subroutine from the main loop. Then I can use exit /b

Disadvantages of subroutine, I would need to define many arguments (about 40), and it could make the code longer and less clear.

Adding inner condition seems to me as the simplest way. Disadvantage is that the structure get a little more complicated when I will add another condition.

Subroutine requires reading array of arguments which can consume some (short) time. But the inner condition doesn't break the loop at all. What is faster?

Re: Is it possible to break loop?

Posted: 25 Jun 2012 06:52
by jeb
doscode wrote: Did you read the help for

...
doscode wrote:Break /? Is very curt


Then you should recognized that the help of break /? explained that the command has no effect on a windows plattform and is only for compatibility of old DOS software.

I asked google: how to break a batch loop

And it shows the answer:

Use goto :label to break a for-loop

Code: Select all

For %%A in (1 2 3) do (
  echo %%A
  goto :myBreak
)
:myBreak

Re: Is it possible to break loop?

Posted: 25 Jun 2012 08:11
by doscode
jeb wrote:Use goto :label to break a for-loop


I've seen the similar:
http://stackoverflow.com/questions/4710 ... tch-script
"One remark, breaking of FOR /L loops does not work as expected, the for-loop always count to the end, but if you break it, the execution of the inner code is stopped, but it could be really slow."

Code: Select all

@echo off
SETLOCAL EnableDelayedExpansion
for %%a in (a b c) DO (
   echo Outer loop %%a
   call :inner %%a
)
goto :eof
:inner
for %%b in (U V W X Y Z) DO (
  if %%b==X (
    echo    break
    goto :break
  )
  echo    Inner loop    Outer=%1 Inner=%%b
)
:break
goto :eof

But the example was used with subroutine

Re: Is it possible to break loop?

Posted: 25 Jun 2012 09:29
by doscode
I already had tested goto in the inner loop before I started to look for help. It failed to me. So I tried your recommandation, in this way:

FOR /F "tokens=1-20 delims=<>" %%A IN ('somefile.txt') DO (
FOR %%Z in ( "%%A", "%%B", "%%C", "%%D", "%%E", "%%F", "%%G", "%%H", "%%I", "%%J", "%%K", "%%L", "%%M", "%%N", "%%O", "%%P", "%%Q") DO (
if !break! EQU 1 (
echo this is error
pause
)
SET /A cnt=!cnt!+1
if !cnt! LSS 4 (
SET IP=!IP!!legalNumber!.
) else (
SET IP=!IP!!legalNumber!
SET /A cnt=0
SET /A break=1
goto :myBreak
)
echo /!cnt!/!IP!

REM Endof For %%Z
)
:myBreak
REM Next code here
)

And it fails to me with error Incorrect syntax

Why?

Re: Is it possible to break loop?

Posted: 25 Jun 2012 09:46
by Fawers
Another way to break a loop is to have a FOR CALLing a "label function".

Code: Select all

@echo off
for /f "tokens=1,2" %%a in ('dir') do (
  call :ToBreakOrNotTobreak "%%a" "%%b"
)


:ToBreakOrNotToBreak
if "%2" == "file(s)" (set /a "files=%1"
) else exit /b

This will call the label for each %%a and %%b.

Another way is to put the entire for loop in a section.

Code: Select all

@echo off
::some code here
call :BreakableLoop
goto :eof

:BreakableLoop
::for loop here (
  ::some code here
  ::some other code here
  ::if CONDITION is MET, then exit /b
  ::some more code here
)

Re: Is it possible to break loop?

Posted: 25 Jun 2012 09:59
by Squashman
You can't break out of the inner loop with a goto without breaking the outer loop as well and you definitely can't break out of the inner loop with a goto to a label at the end of the outer loop.

Re: Is it possible to break loop?

Posted: 25 Jun 2012 10:12
by doscode
I think I know where the problem is. It is not possible to do this:

REM Outer loop starts...
for ... do (
REM Inner loop starts ...
for ... do (
if ... goto :break
)

:break
REM Endof outer loop:
)

Because the error is ") not expected".

When I tooks Jebs example, I changed it to the principle of this:

Code: Select all

echo off
For %%D in (1 2 3) do (
For %%A in (1 2 3) do (
  echo %%A
  goto :myBreak
)
)
:myBreak

Re: Is it possible to break loop?

Posted: 25 Jun 2012 15:11
by Ed Dyreen
Squashman wrote:You can't break out of the inner loop with a goto without breaking the outer loop as well and you definitely can't break out of the inner loop with a goto to a label at the end of the outer loop.
The only thing I use goto for, is to break inner loops without breaking out of the outer subroutine/function.

Code: Select all

@echo off &setlocal enableDelayedExpansion

:main ()
:: (
   :break ()
   :: (
      for /l %%? in (

         1,1,3

      ) do (
         echo.main
         call :loop1 "()"
         goto :break "()"
      )
   :: )
   :break ()
:: )
echo.end &pause &exit /b 0

:loop1 ()
:: (
   :break ()
   :: (
      for /l %%? in (

         1,1,3

      ) do (
         echo.loop1
         goto :break "()"
      )
   :: )
   :break ()
:: )
exit /b 0

Code: Select all

main
loop1
end
Druk op een toets om door te gaan. . .

Re: Is it possible to break loop?

Posted: 25 Jun 2012 16:23
by dbenham
Logically you might want something like the following: (pseudo code)

Code: Select all

for var1 in (list1) do (
  for var2 in (list2) do (
    do something with var1 and var2
    if var2=EndCondition break out of loop2
  )
)

As has been pointed out, you need to use a called subroutine for the inner loop, and you can safely break out of the inner loop and return to the outer loop using GOTO.

But you might fret, the context of the outer loop dissapears while I am in the called subroutine, so I can't access the outer loop variable. No worries...

What hasn't been explained is that the variable from the outer loop is available within the inner loop :D 8)

Given that we are in a subroutine, a simpler approach to breaking out of the inner loop is to use EXIT /B instead of GOTO :LABEL.

Here is an example that demonstrates both concepts. Note how %%A is initially not available within the subroutine. But while inside the inner loop it "magically" reappears.

Code: Select all

@echo off
for %%A in (1 2 3) do (
  echo(
  echo inside outer loop: A=%%A
  call :innerSub
)
exit /b

:innerSub
echo inside innerSub but before inner loop: A=%%A
for %%B in (a b c e e) do (
  echo inside inner loop: A=%%A B=%%B
  if %%B==c exit /b
)
exit /b

output:

Code: Select all

inside outer loop: A=1
inside innerSub but before inner loop: A=%A
inside inner loop: A=1 B=a
inside inner loop: A=1 B=b
inside inner loop: A=1 B=c

inside outer loop: A=2
inside innerSub but before inner loop: A=%A
inside inner loop: A=2 B=a
inside inner loop: A=2 B=b
inside inner loop: A=2 B=c

inside outer loop: A=3
inside innerSub but before inner loop: A=%A
inside inner loop: A=3 B=a
inside inner loop: A=3 B=b
inside inner loop: A=3 B=c


Dave Benham

Re: Is it possible to break loop?

Posted: 25 Jun 2012 21:47
by Aacini
You may get an equivalent behaviour of breaking the inner loop and passing to the next iteration of the outer loop if you enclose the body of inner loop in an IF controled by a break variable:

Code: Select all

@echo off
for %%D in (1 2 3) do (
   set break=
   for %%A in (1 2 3) do (
      if not defined break (
         echo D=%%D, A=%%A
         if %%A equ 2 set break=TRUE
      )
   )
)


Antonio

Re: Is it possible to break loop?

Posted: 25 Jun 2012 23:39
by doscode
Aacini wrote:You may get an equivalent behaviour of breaking the inner loop and passing to the next iteration of the outer loop if you enclose the body of inner loop in an IF controled by a break variable:

Code: Select all

@echo off
for %%D in (1 2 3) do (
   set break=
   for %%A in (1 2 3) do (
      if not defined break (
         echo D=%%D, A=%%A
         if %%A equ 2 set break=TRUE
      )
   )
)


Antonio


This is unbelievable. Your code is so simple and it really works. If I remove the condition so it stopped to worked. When I tried to use it in my inner loop, I have this condition and it does not work:

Code: Select all

    if !ThisIsLegalNumber! EQU 1 (
      REM ECHO THIS IS LEGAL NUMBER
        SET legalNumber=!second!
        SET /A cnt=!cnt!+1
        if !cnt! LSS 4 (
          SET IP=!IP!!legalNumber!.
          ) else (
          SET IP=!IP!!legalNumber!
          SET /A cnt=0
          SET /A Search_IP=0
          REM THIS IS FINISH OF THE LOOP
          set break=TRUE
          )
      )


So it cannot be separated in the else branch or with other commands?

If I change it to:

Code: Select all

    set break=
    if !ThisIsLegalNumber! EQU 1 (
      REM ECHO THIS IS LEGAL NUMBER
        SET legalNumber=!second!
        SET /A cnt=!cnt!+1
        if !cnt! LSS 4 (
          SET IP=!IP!!legalNumber!.
          ) else (
          SET IP=!IP!!legalNumber!
          SET /A cnt=0
          SET /A Search_IP=0
          REM THIS IS FINISH OF THE LOOP
          if !cnt! EQU 4 set break=TRUE
          )
        echo /!cnt!/!IP!
      )


So it still continues in the inner loop. Even the IP address is completed. I have to have some mistake there in the code. Any idea what could be wrong?

Re: Is it possible to break loop?

Posted: 25 Jun 2012 23:49
by Aacini

Code: Select all

set and=if
. . . . .


  set break=

  rem The inner loop start here...

    if !ThisIsLegalNumber! EQU 1 %and% not defined break (
      REM ECHO THIS IS LEGAL NUMBER
        SET legalNumber=!second!
        SET /A cnt=!cnt!+1
        if !cnt! LSS 4 (
          SET IP=!IP!!legalNumber!.
          ) else (
          SET IP=!IP!!legalNumber!
          SET /A cnt=0
          SET /A Search_IP=0
          REM THIS IS FINISH OF THE LOOP
          if !cnt! EQU 4 set break=TRUE
          )
        echo /!cnt!/!IP!
      )

Re: Is it possible to break loop?

Posted: 26 Jun 2012 00:07
by doscode
I don't understand your code, why you write it this way.

if !ThisIsLegalNumber! EQU 1 %and% not defined break
What does it mean? I think that it doesn't solve anything. Will this break the loop or not? Next code there.