3

I'm trying to find a way to make nested for loops work, but this iteration is different than the most popular results (where an OP is looping through directories, or using a numerical for /l loop, etc.)

Instead, I'm trying to figure out how to make this work:

@echo Off
setlocal enabledelayedexpansion enableextensions


for /f "Tokens=1-7 Delims=_" %%P in ("Testing_This_GREAT_Thing_Of_An_IDEA") do (
  Echo %%P
  For %%a in (P Q R S T U V ) do (
    Call set "term=%%%%%%a"
    Call echo !term!
    Call set term=%%term%%
    Call Echo !term!
    Call set term=%%term%%
    Call Echo !term!
    If not "!term!"=="" Call set word.%%a=%%term%%
    Echo word.%%a = "!word.%%a!"
  )
)
pause
exit /b

Desired output of For %%a in (P Q R S T U V) loop would be to have:

word.P=Testing
word.Q=This
word.R=GREAT
word.S=Thing
word.T=Of
word.U=An
word.V=IDEA

Obviously the following would be as expected for the initial loop, but I cannot get the delayed expansion (I assume) to work as expected. . . .

%%P=Testing
%%Q=This
%%R=GREAT
%%S=Thing
%%T=Of
%%U=An
%%V=IDEA
6
  • For what it is worth, I am able to use a Subroutine/function with the inner for loop, calling it using the parsed Tokens as arguments and the Shift command, but was hoping I could use just the nested For Loops instead. Commented Dec 11, 2022 at 8:25
  • Saving another edit to the question - the current output I get is %%P and so forth - just not the expanded variable Commented Dec 11, 2022 at 8:35
  • As I Ponder this, I thought for SURE I saw this answered somewhere a LONG time ago with the great @dbenham providing valuable insight to the For command, but I cannot recall if he determined this kind of iteration was possible or not Commented Dec 11, 2022 at 8:55
  • 4
    There is a much simpler way to build an array from a list using a delimiter. See: dostips.com/forum/viewtopic.php?t=6429 Commented Dec 11, 2022 at 9:57
  • I REALLY like this too - great stuff - wonderful find! I believe I could interpret the code from @Aacini (Assuming he's the very one and same here on beloved SO) - to make (by his first example) something along the lines of set i=1 && set "x=Delimited_String_For_Testing_Purposes" && set "x!i!=%x:_=" & set /A i+=1 & set "x!i!=%" seeing his is making "o" the Delim. Commented Dec 11, 2022 at 14:43

3 Answers 3

2

No, it's not possible (in a single block).

You try to dynamically access a FOR meta variable, but FOR meta variables are recognized only in the parsing phase, before the code block is executed. An inline call can't help here, because a FOR meta variable isn't detected at all in the second parsing round of a call command.

But you could use a helper function, using the fact that you can access all FOR meta variables in any FOR block, even when they are not in the same block.

@echo Off
setlocal enabledelayedexpansion enableextensions


for /f "Tokens=1-7 Delims=_" %%P in ("Testing_This_GREAT_Thing_Of_An_IDEA") do (
  Echo %%P
  For %%a in (P Q R S T U V ) do (
    Call :read_meta_var term %%a
    If not "!term!"=="" Call set word.%%a=%%term%%
    Echo word.%%a = "!word.%%a!"
  )
)
pause
exit /b

:read_meta_var
REM *** %1=Variable to store the result
REM *** %2=Character of the meta variable to read

for %%d in ("dummy") do (
  set "%1=%%%2"
)
Sign up to request clarification or add additional context in comments.

1 Comment

this is almost exactly what I had decided to settle on as I fleshed out the Subroutine I posted. Thank you for confirming my suspicions!
2

Adding another answer I stumbled upon which operates on the premise presented by @T3RR0R's Comment to my original post - @T3RR0R Linked to this article at dostips.com, where we are presented with the idea of parsing substrings from one string using whatever delimiter we want.

Modifying one of the examples set within this article, we can arrive at the following which uses a zero-indexed "array" like we're used to seeing in almost all other programming languages.

set "x=Testing_This_GREAT_Thing_Of_An_IDEA"
set i=0
set "x.!i!=%x:_=" & set /a i+=1 & set "x.!i!=%"
REM output x var's:
set x.

Which yields the fantastically succinct output of:

x.0=Testing
x.1=This
x.2=GREAT
x.3=Thing
x.4=Of
x.5=An
x.6=IDEA

I played around with trying to set "x.a"-"x.g" using variable positioning and the delayed expansion of i where it is asserted that "verb=abcdefghijklmnopqrstuvwxyz", by using:

set "x.!y!=%x:_=" & set /a i+=1 & Call set "y=%%verb:~!i!,1%%" & set "x.!y!=%"

Unfortunately, it always ended with x.a=Testing and nothing else defined, while y=IDEAverb:~7,1 always occurred, boggling my mind. . . I would love to get this to work in a one-liner!

Fortunately, if I take a For /l numerical loop, I can accomplish my goal in 2 lines with the assertion that x and verb are already set previously as described using the original substitution line:

set "x.!i!=%x:_=" & set /a i+=1 & set "x.!i!=%"
For /l %%l in (0,1,!i!) do (For /f "Tokens=1" %%q in ("!verb:~%%l,1!") do ( set "word.%%q=!x.%%l!" ) )

If it is possible to perform this variable substitution/positioning in one line using the calculation to i in one line, this would be fantastic, otherwise, for the sake of sanity, an extra line is not a problem for me.

1 Comment

See my answer with the desired one-liner solution...
2

I think you should read the whole article at dostips.com because in the last page this method is explained:

@echo off
setlocal EnableDelayedExpansion

set "str=Testing_This_GREAT_Thing_Of_An_IDEA"
set "vars=P Q R S T U V"

set "p=%%" & set "v=%vars: =" & set "s=!str:*_=!" & call set "word.!v!=!p!str:_!s!=!p!" & set "str=!s!" & set "v=%" & set "word.!v!=!s!"

set word

Output:

word.P=Testing
word.Q=This
word.R=GREAT
word.S=Thing
word.T=Of
word.U=An
word.V=IDEA

EDIT: New method added

After carefully read your answer, I think this is what you are looking for:

@echo off
setlocal EnableDelayedExpansion

set "x=Testing_This_GREAT_Thing_Of_An_IDEA"
set "verb=abcdefghijklmnopqrstuvwxyz"

set "p=%%" & set i=0 & set "x.%verb:~0,1%=%x:_=" & set /a i+=1 & call set "x.!p!verb:~!i!,1!p!=%"

set x

Finally, a more "traditional" method, using just FOR's:

@echo off
setlocal EnableDelayedExpansion

set "x=Testing_This_GREAT_Thing_Of_An_IDEA"
set "y=P Q R S T U V"

for %%n in (^"^
%Don't remove this line%
^") do for %%a in ("!x:_=%%n!") do (
   for /F "tokens=1*" %%b in ("!y!") do set "word.%%b=%%~a" & set "y=%%c"
)

set word

5 Comments

Is there an emoji for "MindBlown" ??? I must break this down so I understand. . . set p=%% is used in the call set line to instantiate the fact that I want to convert %%verb:~!i!,1%% appropriately at the end - that's insane. Now, I did read the whole article, but so many of those items were WAY above my head at the time of day I was reading. Looking at the original option, it was to satisfy the original posting using "P Q R S" and splitting *BOTH* strings by their respective delimiters "_" and " " respectively . . . Do I have this correct?
And this For Loop - HOW ON EARTH do you figure this out?!? So - for %%n . . . sets up what exactly - is it using the crlf to do something? If you could break this last part down a little more - this would be wonderful - truly a magical solution. Thank you!
The method to split two variables in the same line is described with detail at this post. The for %%n . . . trick replaces the underscore by a CrLf so it splits one string in several lines. In this way, you don't need to worry about how many items a string have (that must be processed with variable number of tokens=1-7 and different %%P %%Q ... parameters). Instead, process each part with a standard (no /F option) FOR command.
Do you know that you can change the selected Best Answer if you wish? ;)
I can - however - for the project I'm working on, I settled on the answer provided by Jeb initially - I still need to work out the logic in my mind how I'd make this answer tie into what was built - as it stands, sending everything to a subroutine allows me some flexibility on what I'm doing with every token at run-time which (at least on first glance) will be more difficult in my mind until I can wrap my head around this better. I'm thinking long term I might switch to this, and produce these substrings and then do what I need after separate from the loop. A project for another day though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.