Meow
Meow

Reputation: 19071

How to loop through comma separated string in batch?

Windows

Based on the post (dos batch iterate through a delimited string), I wrote a script below but not working as expected.

Goal: Given string "Sun,Granite,Twilight", I want to get each theme value in loop so that I can do some processing with the value.

Current output is not corrct:

list = "Sun,Granite,Twilight"
file name is "Sun Granite Twilight"

For the first iteration it should be:

list = "Sun,Granite,Twilight"
file name is "Sun"

Then second iteration should be "file name is "Granite" and so on. What am I doing wrong?

Code:

set themes=Sun,Granite,Twilight

call :parse "%themes%"
goto :end

:parse
setlocal
set list=%1
echo list = %list%
for /F "delims=," %%f in ("%list%") do (
    rem if the item exist
    if not "%%f" == "" call :getLineNumber %%f
    rem if next item exist
    if not "%%g" == "" call :parse "%%g"
)
endlocal

:getLineNumber
setlocal
echo file name is %1
set filename=%1
endlocal

:end

Upvotes: 29

Views: 71102

Answers (4)

RGuggisberg
RGuggisberg

Reputation: 4750

I made a few modifications to your code.

  1. Need goto :eof at end of subroutines and at end of main routine so you don't fall into subroutines.
  2. tokens=1* (%%f is first token; %%g is rest of the line)
  3. ~ in set list=%~1 to remove quotes so quotes don't accumulate

    @echo off
    set themes=Sun,Granite,Twilight
    
    call :parse "%themes%"
    pause
    goto :eof
    
    :parse
    setlocal
    set list=%~1
    echo list = %list%
    for /F "tokens=1* delims=," %%f in ("%list%") do (
        rem if the item exist
        if not "%%f" == "" call :getLineNumber %%f
        rem if next item exist
        if not "%%g" == "" call :parse "%%g"
    )
    endlocal
    goto :eof
    
    :getLineNumber
    setlocal
    echo file name is %1
    set filename=%1
    goto :eof
    

Upvotes: 12

Brent
Brent

Reputation: 391

I took Aacini's answer and only slightly modified it to remove the quotes, so that the quotes can be added or removed as it would be in the desired command.

@echo off
set themes=Hot Sun,Hard Granite,Shimmering Bright Twilight
for %%a in ("%themes:,=" "%") do (
    echo %%~a
)

Upvotes: 29

Aacini
Aacini

Reputation: 67206

This is the way I would do that:

@echo off
set themes=Sun,Granite,Twilight
echo list = "%themes%"
for %%a in ("%themes:,=" "%") do (
   echo file name is %%a
)

That is, change Sun,Granite,Twilight by "Sun" "Granite" "Twilight" and then process each part enclosed in quotes in a regular (NO /F option) for command. This method is much simpler than an iterative for /F loop based on "delims=,".

Upvotes: 53

dazedandconfused
dazedandconfused

Reputation: 3186

Looks like it needed the "tokens" keyword...

@echo off
set themes=Sun,Granite,Twilight

call :parse "%themes%"
goto :end

:parse
setlocal
set list=%1

for /F "delims=, tokens=1*" %%f in (%list%) do (
    rem if the item exist
    if not "%%f" == "" call :getLineNumber %%f
    rem if next item exist
    if not "%%g" == "" call :parse "%%g"
)
endlocal
goto :end

:getLineNumber
setlocal
echo file name is %1
set filename=%1
endlocal 

:end

Upvotes: 0

Related Questions