'for' statement in macro will not accept 'tokens' argument from another 'for' statement. Why?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
techtony
Posts: 4
Joined: 23 Apr 2018 06:19

'for' statement in macro will not accept 'tokens' argument from another 'for' statement. Why?

#1 Post by techtony » 23 Apr 2018 06:49

Code: Select all

   set get_element=^
   for /l %%N in (1 1 2) do if %%N equ 2 (^
      for /f "tokens=1-3 delims= " %%A in ("^!args^!") do (^
         for /f "tokens=%%B delims=," %%X in (^!%%A^!) do (^
            set "%%C=%%X"^
         )^
      )^
   ) else set args=


   set lst="one,two,three"
   %get_element% lst 2 el
   echo,el: [%el%]
Output:

%B delims=," was unexpected at this time.
el: []

A function that does the same thing, however, does work:

Code: Select all

:GetElement
   for /f "tokens=%2 delims=," %%a in (!%1!) do (
      set %3=%%a
	)
exit /b
(Aside: Can the tab size in the code editor be changed? (I used 3 spaces in this post).)
Last edited by techtony on 23 Apr 2018 19:22, edited 2 times in total.

dbenham
Expert
Posts: 2390
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: 'for' statement in macro will not accept 'tokens' argument from another 'for' statement. Why?

#2 Post by dbenham » 23 Apr 2018 07:01

Because FOR /F options are parsed and interpreted before FOR variables are expanded.
The fact that you are using FOR /F within a macro has nothing to do with the problem.

It all makes sense if you study How does the Windows Command Interpreter (CMD.EXE) parse scripts?. You cannot use FOR variables or delayed expansion as options to IF or FOR because they are expanded too late. The IF and FOR variables are interpreted in phase 2. But FOR variables aren't expanded until phase 4, and delayed expansion is in phase 5.


Dave Benham

techtony
Posts: 4
Joined: 23 Apr 2018 06:19

Re: 'for' statement in macro will not accept 'tokens' argument from another 'for' statement. Why?

#3 Post by techtony » 23 Apr 2018 07:45

The macroization attempt, though, does introduce the problem. The macroization was, of course, done to avoid the overhead of a function call (which would have been a nice little snippet if it would have worked!). Thanks for your explanation.

pieh-ejdsch
Posts: 232
Joined: 04 Mar 2014 11:14
Location: germany

Re: 'for' statement in macro will not accept 'tokens' argument from another 'for' statement. Why?

#4 Post by pieh-ejdsch » 23 Apr 2018 11:53

a little workaround to do this ...

Code: Select all

set "varCount=!varName!"
set "varCount=!varCount:?=x"
set "varCount="=x!"
set "varCount="!varCount:,=" "!""
set "#=0"
for %%L in (!varCount!) do  ( set /a #+=1
  if !#! equ !TOKEN#!  for /f "delims=," %%S in ("!varName!") do set "newVar=%%S"
  set "varName=!varName:*,=!,")
Last edited by pieh-ejdsch on 25 Apr 2018 13:23, edited 1 time in total.

penpen
Expert
Posts: 1864
Joined: 23 Jun 2013 06:15
Location: Germany

Re: 'for' statement in macro will not accept 'tokens' argument from another 'for' statement. Why?

#5 Post by penpen » 23 Apr 2018 16:57

Another option is to use string replacement within environment variables:

Code: Select all

@echo off
setlocal enableExtensions enableDelayedExpansion

set get_element=^
for /l %%N in (1 1 2) do if %%N equ 2 (^

^ for /f "tokens=1-3 delims= " %%A in ("^!args^!") do (^

^  for /f "tokens=_tokens delims=," %%X in (^^^!%%A^^^!) do (^

^   set "%%C=%%X"^

^  )^

^ )^

^) else set args=

set "get_element"

set lst="one,two,three"
%get_element:_tokens=2% lst 2 el
echo,el: [%el%]
Result:

Code: Select all

get_element=for /l %N in (1 1 2) do if %N equ 2 (
 for /f "tokens=1-3 delims= " %A in ("!args!") do (
  for /f "tokens=_tokens delims=," %X in (!%A!) do (
   set "%C=%X"
  )
 )
) else set args=
el: [two]
penpen

techtony
Posts: 4
Joined: 23 Apr 2018 06:19

Re: 'for' statement in macro will not accept 'tokens' argument from another 'for' statement. Why?

#6 Post by techtony » 25 Apr 2018 06:02

penpen wrote: "Another option is to use string replacement within environment variables."

That looked promising, but as the element number is likely to come from a variable and not a literal, that technique doesn't work. (That detail was not in the OP, because I was just pondering the situation, but it still seems like a good problem, but perhaps not solveable with batch).

T3RRY
Posts: 83
Joined: 06 May 2020 10:14

Re: 'for' statement in macro will not accept 'tokens' argument from another 'for' statement. Why?

#7 Post by T3RRY » 12 Oct 2020 10:24

Simpler would be:

Code: Select all

@Echo off
Setlocal DisableDelayedExpansion
 Set "Extract=Set "r=1"&For %%v in (!Tkns!)Do Set "#n=1"&For %%n in (1 2)Do if %%n==2 (For %%G in (!Var!)Do If "!#n!"=="%%v" (Set "!rv![!r!]=%%~G"&Set /A "#n+=1"& Set /A "r+=1")Else (Set /A "#n+=1"))Else Set Rv="
 Set "CLR=(For /F "tokens=1,2 Delims==" %%G in (' Set Var[ ') Do Set "%%~G=")2> Nul "
Setlocal EnableDelayedExpansion

 set "lst=one,two,three,four"
 Set Tkns=1 3 & %Extract:Var=lst%result
 Set result[
 %CLR:Var=result%
 Set result[ 2> Nul
ENDLOCAL & ENDLOCAL

Post Reply