As Twisty Impersonator says, you may be dealing with an X-Y Problem.
X
Given an input file that looks like
rep1=The
url1=quick
rep2=brown
url2=fox
︙
you want to run commands like
program.exe -param1 The -installIU quick
program.exe -param1 brown -installIU fox
︙
I would do that like this:
setlocal enabledelayedexpansion
set phase=1
for /f "delims== tokens=1*" %%A in (list.ini) do (
if !phase! == 1 (
set "saverep=%%B"
set phase=2
) else (
program.exe -param1 "!saverep!" -installIU "%%B"
set phase=1
)
)
The for statement reads everything before the first = into %%A
and everything after it into %%B.
(Either value may contain space(s).
We do not expect %%A to ever contain spaces
because it will be repN
or urlN.
The %%B value may contain additional = signs.)
The phase variable alternates between 1 and 2.
It is 1 when we read a repN
and 2 when we read a urlN.
When we read a repN (when phase is 1),
save the value in saverep (and set phase to 2).
When we read a urlN (when phase is 2),
run the program using the saved rep and the URL value
from the current line.
I added quotes ("!saverep!"
and "%%B") to handle values with spaces in them.
This totally ignores the variable names in the file
(i.e., the repN and urlN strings
that appear to the left of the =),
even though we have access to them (in %%A).
If you are concerned about possible data integrity issues
(skipped entries, invalid entries, multi-line entries, etc.) in your file,
you can certainly add code to do sanity checks on %%A.
Y
Given an input file that looks like
rep1=The
url1=quick
rep2=brown
url2=fox
︙
you want to read the file, set variables rep1=The, url1=quick,
rep2=brown, url2=fox, etc… in the environment,
and then loop through those environment variables and run commands like
program.exe -param1 The -installIU quick
program.exe -param1 brown -installIU fox
︙
Here’s a way to do that:
Set /a _Lines=0
For /f %%j in ('Find "" /v /c ^< %_File%') Do Set /a _Lines=%%j
::counting how many times for loop to go
set /a iterate=(%_Lines%-0)/2
::read the ini file
for /f "delims=" %%a in (list.ini) do set %%a
setlocal enableextensions enabledelayedexpansion
FOR /L %%I IN (1,1,%iterate%) DO (
set count=%%I
call set "rep=%%rep!count!%%"
call set "url=%%url!count!%%"
program.exe -param1 "!rep!" -installIU "!url!"
)
This is obviously fairly close to what you have now.
Notes:
- You probably don’t need to do
Set /a _Lines=0
(i.e., you could probably just leave out that line).
- You might want to verify that
_Lines has a valid value
after the For … ('Find …) … command.
To be really paranoid,
you could initialize _Lines to a totally invalid value
(like none or null).
If _Lines is still the initial value
after the For … ('Find …) … command, that means that it failed.
If _Lines is anything other than an even, positive integer,
then there’s something wrong.
- If
_Lines is 0 (zero) or an odd, positive integer,
then there’s something wrong with your file.
- If
_Lines is anything else
(a negative number, a non-integer like 3.14, or a non-number like foo),
then there’s something wrong with the Find command.
- I set
iterate to (%_Lines%-0)/2
to make it obvious that I had made a change.
I believe that you should be able to just set /a iterate=%_Lines%/2.
After all, if the file is 42 lines long, then you have 21 data points
(i.e., 21 pairs of values, needing 21 command executions), right?
If you have a good reason for subtracting one,
then put the -1 back in (but you might want to document the reason,
if only as a comment in your code).
- I left
enableextensions in there, because you had it,
but, as far as I know, you don’t need it.
- Since we’re doing a
FOR /L loop, we don’t also need to do arithmetic
on a count variable; just set it equal to the loop index.
Finally, the payoff:
call set "rep=%%rep!count!%%"
call set "url=%%url!count!%%"
If count is (for example) 17,
then the first command will build a string that looks like "rep=%rep17%".
We then “call” the set "rep=%rep17%" command,
which re-parses / re-interprets / evaluates that command
and sets rep equal to the value of %rep17%.
(Obviously the second line does the exact same thing for url.)
I got the idea for this way of using the call statement
from Squashman’s answer to batch increment variable string.
Variations are discussed in other threads;
e.g., Batch file. Variable in variable
(although not all the answers to that question work in loops).
Y2
The second half of the above might be clearer if I present it like this:
setlocal enabledelayedexpansion
FOR /L %%I IN (1,1,%iterate%) DO (
call :kludge rep%%I url%%I
program.exe -param1 "!rep!" -installIU "!url!"
)
goto :eof
:kludge
set "rep=!%1!"
set "url=!%2!"
exit/b
Here we are building strings like rep17 and url17
and passing them to the :kludge subroutine,
where they are re-parsed in the context
set "rep=!rep17!"
set "url=!url17!"
Note that this solution eliminates the count variable.
Yikes!
Here’s another variation that’s even shorter, although perhaps less clear:
setlocal enabledelayedexpansion
FOR /L %%I IN (1,1,%iterate%) DO (
call set "rep=%%rep%%I%%"
call set "url=%%url%%I%%"
program.exe -param1 "!rep!" -installIU "!url!"
)
The cryptic expression %%rep%%I%% is parsed like this:
%%rep%%I%%
▲▲ ↑-↑▲▲
▲▲______▲▲
- First the
%%I is recognized as the loop index variable
and is replaced with its value (e.g., 17),
resulting in a string like %%rep17%%.
- The remaining
%% pairs are reduced
to individual % characters: %rep17%.
- The
%rep17% expression is interpreted as the 17th rep variable.
Note that this solution also avoids using a count variable.