I'm trying to write a text adventure in batch, so I want to know how I can split variable like set userinput=take book and turn it into an array. I want to be able to write a program that will split strings into array items at each space. I've done this in a lot of other languages. There are several other questions like this, but I don't feel like they answer my question.
2 Answers
This task is probably much more difficult than you realize. There are lots of "simple" methods, but none of the simple ones are robust.
For example, a simple FOR loop can parse out individual tokens, but it will be broken by *, ?, and possibly ".
A robust solution requires a significant amount of code.
Here is my solution, with extensive comments:
@echo off
:: Start out with delayed expansion disabled, and define "user input"
:: I intentionally include "problem" characters
setlocal disableDelayedExpansion
set "userinput=take book! & ;MustPreserve EmptyLinesAreIgnored"
:: Initialize count
set "cnt=0"
:: Enable and use delayed expansion to protect against poison characters
setlocal enableDelayedExpansion
:: Substitute <LineFeed> for each <space>
(set parsed=!userinput: =^
%= Do not remove or alter this line =%
!)
:: Iterate each line, setting delims and eol to <space> to preserve all tokens
for /f "eol= delims= " %%A in ("!parsed!") do (
%= Return to delayed expansion disabled on first iteration, else ! is lost =%
if "!" equ "" endlocal
%= Increment the count =%
set /a cnt+=1
%= Temporarily enable delayed expansion to capture current count in FOR variable =%
setlocal enableDelayedExpansion
for %%N in (!cnt!) do (
endlocal
%= Save the array value =%
set "token.%%N=%%A"
)
)
::Print the results. Safe array access requires delayed expansion
setlocal enableDelayedExpansion
for /l %%N in (1 1 !cnt!) do echo token.%%N=!token.%%N!
It looks a bit better without all the comments
@echo off
setlocal disableDelayedExpansion
set "userinput=take book! & :MustPreserveColon ;MustPreserve EmptyLinesAreIgnored"
set "cnt=0"
setlocal enableDelayedExpansion
(set parsed=!userinput: =^
%= Do not remove or alter this line =%
!)
for /f "eol= delims= " %%A in ("!parsed!") do (
if "!" equ "" endlocal
set /a cnt+=1
setlocal enableDelayedExpansion
for %%N in (!cnt!) do (
endlocal
set "token.%%N=%%A"
)
)
setlocal enableDelayedExpansion
for /l %%N in (1 1 !cnt!) do echo token.%%N=!token.%%N!
And here is the output:
token.1=take
token.2=book!
token.3=&
token.4=;MustPreserve
token.5=EmptyLinesAreIgnored
Comments
@echo off
color 08 & Title %~dpnx0
setlocal enabledelayedexpansion
echo.______S__T__A__R__T_______
echo. ArrayNumber: HierarchieChange inside of the for
echo. or start lenght with 1
echo. ArrayPosi Zero is not defined in this example
set array[4]=you
set array=one two
set array=!array! three
set /a lenght=0
for %%a in (!array!) do (
set array[!lenght!]=%%a
set /a lenght+=1
)
echo.___!array[2]!___!array[1]!___!array[0]!
echo.&echo.
echo.******************************************
for /l %%a in (!lenght!,-1, -1) do echo !array[%%a]!
echo._______________________________________________
for /l %%a in (0,1,!lenght!) do echo !array[%%a]!
echo.&echo.____________without any errors____________________
set /a lenght-=1
for /l %%a in (0,1,!lenght!) do echo !array[%%a]!
echo.-----------------------------------------------------
echo.-----------------------------------------------------
echo. but the charPos 1 is zero when u splitt Strings
set splitt=ABCD
echo !splitt!>TSCHHHHHHHHHHUUUUUUUUUUUUUNGBamBam.txt
for %%a in (TSCHHHHHHHHHHUUUUUUUUUUUUUNGBamBam.txt) do set /a chars=%%~za -2
echo. chars: !chars!
echo. char3: !splitt:~2,1!
for /l %%a in (0,1,!chars!) do echo. %%a !splitt:~%%a,1!
echo._________E__N__D__________
timeout 3 >nul
pause
1 Comment
Michael Roswell
Please add some text explaining your answer, and ideally, comment your code. The currently accepted answer from @dbenham is a good model.