2

I want to parse through a single line of text where the words are separated by a space and store each word in its own array simulating variable. According to ss64 I should be able to do this. I may not be understanding delims or tokens because my code works for 1 iteration and stops.

::@echo off
setlocal enabledelayedexpansion
set string=foo bar baz
set /a index=0

for /F "tokens=* delims= " %%i in ("foo bar baz") do (
    echo %%i
    echo !index!
    set words[%index%]=%%i
    set /a index+=1
    echo !index!
)

set words[

Here is the output I get with debug echoes:

C:\Users\isimm\Desktop\batintercept>stringparse.cmd

C:\Users\isimm\Desktop\batintercept>setlocal enabledelayedexpansion

C:\Users\isimm\Desktop\batintercept>set string=foo bar baz

C:\Users\isimm\Desktop\batintercept>set /a index=0

C:\Users\isimm\Desktop\batintercept>for /F "tokens=* delims= " %i in ("foo bar baz") do (
echo %i
 echo !index!
 set words[0]=%i
 set /a index+=1
 echo !index!
)

C:\Users\isimm\Desktop\batintercept>(
echo foo bar baz
 echo !index!
 set words[0]=foo bar baz
 set /a index+=1
 echo !index!
)
foo bar baz
0
1

C:\Users\isimm\Desktop\batintercept>set words[
words[0]=foo bar baz

tokens=* gives me the above output, tokens=1,2,3 gives me only the first word, tokens=1 or tokens=2 or tokens=3 gives me the 1st, 2nd, or 3rd word. As I understand it "delims= " is redundant because by default spaces are used but it's the same whether I include delims or not.

I also tried using underscores in case there is some bug with spaces and also tried putting the text in a foo.txt file instead of a literal string. In both cases I get the same result as with the original string.

The output I'm expecting is:

words[0]=foo
words[1]=bar
words[2]=baz
1
  • You seem to misinterpret how the for /F loop behaves: it does not iterate over the individual tokens defined by the tokens= and delims= options, it iterates over lines and returns all tokens extracted from a line in one iteration (occupying subsequent loop meta-variables as needed). Type for /? into a Command Prompt window to get a more detailed description… Commented Sep 15, 2021 at 17:26

2 Answers 2

6

You may use this simpler method:

@echo off
setlocal EnableDelayedExpansion

set string=foo bar baz
set /a index=0

set "words[%index%]=%string: =" & set /A index+=1 & set "words[!index!]=%"

set words[

If you want to realize where the magic is, remove @echo off line, run the Batch file and carefully review the screen. Further details at Split string with string as delimiter

EDIT: New method added

You may also use this somewhat cryptic method:

@echo off
setlocal EnableDelayedExpansion

set string=foo bar baz
set /a index=0

for /F %%i in (^"!string: ^=^
% Do not remove this line %
!^") do (
   set words[!index!]=%%i
   set /A index+=1
)

set words[

In this method the spaces are replaced by a LF ASCII character... ;)

Sign up to request clarification or add additional context in comments.

4 Comments

I see where the magic is but don't understand the magic. I've been looking for something in Microsoft docs and on ss64 that mentions this and haven't found anything yet. I'm confused as to how this works without being in a loop. Seems like this is all about how delayed expansion works and what happens when you inject commands or expressions into the set command. 2 things I clearly don't understand and will need to keep looking into. But it works great so thanks.
You may read a detailed discussion about this technique at this thread. PS - Do you know that you may change your selected best answer if you wish? ;)
You may also read the comment below this answer
What happened? Is the method clearer now?
3

I have tried this way and it worked for me:

@echo off & setlocal
setlocal enabledelayedexpansion
set string=foo bar baz
set /a index=0

rem temporaryVariable value always changes in the for loop.
set temporaryVariable=%string%

:loop
for /f "tokens=1*" %%a in ("%temporaryVariable%") do (
   set words[%index%]=%%a
   set /a index+=1
   set temporaryVariable=%%b
   )
if defined temporaryVariable goto :loop

set words[

I have based my answer on this one: https://stackoverflow.com/a/19009701/12367987

Comments

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.