Michal Heneš
Michal Heneš

Reputation: 302

Batch - for loop inside for loop

Is it possible to have for loop inside another for loop ?

I have two files, the first file contains

...
"bla","bli","blu",XX
"bla","bli","blu",YY
...

And the second one contains:

...
XX,some string
XX,some string
YY,diferent string
YY,diferent string
...

And what I want to do is write to one file lines like :

...
"bla","bli","blu",some string
"bla","bli","blu",diferent string
...

My best try isn't working

for /f "tokens=1-10 delims=," %%1 in (semi-final.txt) do (
    :: echo "bla","bli","blu"
echo %%1,%%2,%%3,%%4,%%5,%%6, | tr -d "\r\n" >> final.txt

    :: set var=XX  or set var=YY
set var=%%7

for /f "tokens=1,2 delims=," %%1 in (codes.txt) do (
            :: Find XX in codes.txt for exchange
    if /i "%%2"=="!var!" echo %%1, | tr -d "\r\n" >> final.txt
)

    ::Other echo after that XX , isn't important
echo %%7,%%8,%%9,%%10 >> final.txt
)

EDIT:

I have problem with SHIFT :/ commented in code below

@echo off
setlocal EnableDelayedExpansion

for /f "tokens=1-11 delims=, skip=1" %%1 in (semi-final.txt) do (
    echo %%1,%%2,%%3,%%4,%%5,%%6, >> final.txt

    set var=%%7
    set b=!var:~2,2!

        call :inner !b!

        shift
        shift
        shift
        :: Still %%6 is the same asi in first command

    echo %%6,%%7,%%8,%%9 >> final.txt
)
goto :eof

:inner
for /f "tokens=1,2 delims=," %%X in (codes.txt) do (
    IF /i "%%Y"=="!b!" ( 
        echo '%%X', >> final.txt
            goto :next
    )
)
echo '', >> final.txt
:next
goto :eof

Upvotes: 0

Views: 15794

Answers (2)

dbenham
dbenham

Reputation: 130819

You have still got a number of problems.

  • FOR variable names are a single character, and the sequence when using multiple tokens is in ASCII order. So the variable after %%9 is %%:. It is impossible to have a FOR variable named %%10.

  • The SHIFT command only operates on batch arguments, not on FOR variables. Even though you opted to use digits for your FOR variables, it does not mean you can SHIFT them.

  • There is no need to SHIFT FOR variables, simply use alpha characters to make it easy to figure out which variables to use. It then becomes simple to process up to 26 FOR variables in one loop. Also, you can specify which tokens you want: FOR /F "tokens=1-7,9-11 delims=," %%A will assign %%A-%%G to tokens 1-7, and %%H-%%J to tokens 9-11.

There are significant improvements that can be made.

  • There is no reason to use multiple ECHOs with TR to print a single line. Simply delay printing any info until you have the entire line.

  • You can use FINDSTR to quickly find your matching line, and use another FOR /F to parse out the desired value. This is much faster than reading the entire 2nd file with FOR /F.

  • Using append mode within a loop is inefficient - it takes time for the redirection to open the file and position the pointer. It is much faster to enclose the entire loop within another set of parentheses and redirect only once.

  • There is no need for a CALLed subroutine. Everything can be done within the main loop.

Give this a try:

@echo off
(
  for /f "tokens=1-7,9-11" %%A in (semi-final.txt) do (
    for /f "tokens=2" %%X in ('findstr /bl "%%G," codes.txt') do (
      echo %%A,%%B,%%C,%%D,%%E,%%F,%%X,%%H,%%I,%%J
    )
  )
)>final.txt

If code.txt may have multiple lines with the same code, and you only want the value for the first found line, then you will need a subroutine. Normally you cannot access a FOR variable except within the direct scope of the loop. So you would not expect to be able to CALL a subroutine within a loop and still reference the loop variables in the subroutine. But there is a little known feature that all FOR variables for still active loops are accessible if you are within the scope of another FOR variable.

@echo off
(for /f "tokens=1-7,9-11" %%A in (semi-final.txt) do call :lookup "%%G")>final.txt

:lookup
for /f "tokens=2" %%X in ('findstr /bl "%~1," codes.txt') do (
  echo %%A,%%B,%%C,%%D,%%E,%%F,%%X,%%H,%%I,%%J
  exit /b
)

Upvotes: 1

Avish
Avish

Reputation: 4626

You're using the same FOR variable (%%1) for the two loops. Since they are nested, you should use different variables. The first for loop claims 10 variables (since you asked for 10 tokens), so for the second one you'll need different variables. Try using %%X in the second loop (which would use %%X and %%Y instead of %%1 and %%2).

Upvotes: 0

Related Questions