Page 1 of 1

"For /f" string needs to run only once

Posted: 08 Dec 2011 01:48
by Rileyh
Hi guys,
I have a "for /f" string:

Code: Select all

@echo off
setlocal enabledelayedexpansion
set "$match=(values here vary)"
set "$file=test.txt"
for /f "tokens=1-2*" %%a in ('findstr /b /i "!$match!" "!$file!"') do (
) set "b=%%a"
set "rest=!b:*$match=!"
(do something here)
)

When I run this code (can I note that it is run as a block in a batch file that has this same code over and over) it finds all occurrences, not just the one. I need it to find it only once and then move on wit the batch file.

Can you show me how to do this?

Regards,
Rileyh

Re: "For /f" string needs to run only once

Posted: 08 Dec 2011 02:14
by Ed Dyreen
'

Code: Select all

@echo off &setlocal enabledelayedexpansion

set "$match=(values here vary)"
set  "$file=test.txt"

set "b=" &for /f "tokens=1-2*" %%a in (
   'findstr /bi "!$match!" "!$file!"'
) do if not defined b (
   set "b=%%a"
   set "rest=!b:*$match=!"
   REM *****(do something here)*****
)

Re: "For /f" string needs to run only once

Posted: 08 Dec 2011 07:34
by dbenham
better yet:

Code: Select all

@echo off
setlocal enabledelayedexpansion
set "$match=(values here vary)"
set "$file=test.txt"
findstr /b /i "!$match!" "!$file!" >nul && do something if match is found

Be careful - FINDSTR without using /C option defaults to interpreting the search string as a regular expression :!: Use the /L option to treat it as a literal.

Dave Benham

Re: "For /f" string needs to run only once

Posted: 09 Dec 2011 03:20
by orange_batch
Here's a solution that should be better than Ed's, since it doesn't keep iterating doing nothing but if defined comparisons, this is how you typically break out of a for loop in batch.

Pseudo-code:

Code: Select all

for ... ... (
code ...
goto break
)
:break

Can be used any number of times in your scripts, as goto will always go to the first label found after where it's executed. Of course, you can't go to a specific break though if you have multiple copies.

Re: "For /f" string needs to run only once

Posted: 09 Dec 2011 07:13
by dbenham
orange_batch wrote:Can be used any number of times in your scripts, as goto will always go to the first label found after where it's executed. Of course, you can't go to a specific break though if you have multiple copies.

Actually you can re-use the same label like this BECAUSE it always goes to the first matching label found from current position. :wink:

Code: Select all

for ... do (
  ...
  goto :break
)
:break

for ... do (
  ...
  goto :break
)
:break

The above will actually work as desired every time. But this is highly discouraged as it is confusing.

orange_batch wrote:since it doesn't keep iterating doing nothing

The goto :break is much faster because the DO clause is skipped after the first execution of the GOTO. But the iterations are completed. This script will never end :!:

Code: Select all

@echo off
for /l %%a in (1 0 1) do goto :break
:break


Dave Benham

Re: "For /f" string needs to run only once

Posted: 09 Dec 2011 17:00
by jeb
dbenham wrote:The goto :break is much faster because the DO clause is skipped after the first execution of the GOTO. But the iterations are completed. This script will never end :!:


The iterations are only fully "completed" with FOR /L, FOR /F can be break instantly.
FOR /R can't be brake, but the ECHO ON-output will be suppressed.

Code: Select all

@echo on
cls
for /F %%a in (1 2 3) do (
  echo %%a
  goto :break
)
:break

for /L %%a in (1 1 3) do (
  echo %%a
  goto :break
)
:break

for /R %%a in (1 2 3) do (
  echo %%a
  goto :break
)
:break
exit /b


jeb

Re: "For /f" string needs to run only once

Posted: 09 Dec 2011 18:48
by orange_batch
dbenham wrote:
orange_batch wrote:Can be used any number of times in your scripts, as goto will always go to the first label found after where it's executed. Of course, you can't go to a specific break though if you have multiple copies.

Actually you can re-use the same label like this BECAUSE it always goes to the first matching label found from current position. :wink:

Code: Select all

for ... do (
  ...
  goto :break
)
:break

for ... do (
  ...
  goto :break
)
:break

The above will actually work as desired every time. But this is highly discouraged as it is confusing.

orange_batch wrote:since it doesn't keep iterating doing nothing

The goto :break is much faster because the DO clause is skipped after the first execution of the GOTO. But the iterations are completed. This script will never end :!:

Code: Select all

@echo off
for /l %%a in (1 0 1) do goto :break
:break


Dave Benham


Actually all of that is entirely what I meant by what I wrote, lol. 8) I'm saying you can use break any number of times, but you can't go to a specific one other than the first one found of course.