Ok. I'll try to be as clearer as possible to not be misunderstood...
In Windows Batch files a variable name should begin with letter and may include any valid character, where valid characters are: #$'()*+,-.?@[]_`{}~ besides letters and digits.
This means that from cmd.exe point of view, SET NORMAL_NAME=123
is exactly the same than SET A#$'()*+,-.?@[\]_{}~=123
and also than SET VECTOR[1]=123
; all three are normal variables. This way, is up to you to write variable names in the form of array elements:
set elem[1]=First element
set elem[2]=Second one
set elem[3]=The third one
This way, echo %elem[2]%
will show Second one
.
If you want to use another variable as index, then you must know that the replacement of variables enclosed in percents by their values is parsed from left to right; this mean that:
set i=2
echo %elem[%i%]%
don't give the desired result because it mean: show the value of elem[
variable, followed by i
, followed by the value of ]
variable.
To solve this problem you must use Delayed Expansion, that is, insert setlocal EnableDelayedExpansion
command at beginning, enclose index variables in percents, and enclose array elements in exclamation marks:
setlocal EnableDelayedExpansion
set elem[1]=First element
set elem[2]=Second one
set elem[3]=The third one
set i=2
echo !elem[%i%]!
You may also use parameters of FOR commands as indexes: for /L %%i in (1,1,3) do echo !elem[%%i]!
. You must use !index! to store values in array elements when the index is changed inside a FOR or IF: set elem[!index!]=New value
. To get the value of an element when the index change inside FOR/IF enclose the element in double percents and precede the command with call
. For example, to move a range of array elements four places to left:
for /L %%i in (%start%,1,%end%) do (
set /A j=%%i + 4
call set elem[%%i]=%%elem[!j!]%%
)
Another way to achieve previous process is using an additional FOR command to change the delayed expansion of the index by an equivalent replaceable parameter, and then use the delayed expansion for the array element. This method run faster than previous CALL:
for /L %%i in (%start%,1,%end%) do (
set /A j=%%i + 4
for %%j in (!j!) do set elem[%%i]=!elem[%%j]!
)
This way, Batch files behaves like it manage arrays. I think the important point here is not to discuss if Batch manage arrays or not, but the fact that you may manage arrays in Batch files in an equivalent way of other programming languages.
@echo off
setlocal EnableDelayedExpansion
rem Create vector with names of days
set i=0
for %%d in (Sunday Monday Tuesday Wednesday Thrusday Friday Saturday) do (
set /A i=i+1
set day[!i!]=%%d
)
rem Get current date and calculate DayOfWeek
for /F "tokens=1-3 delims=/" %%a in ("%date%") do (
set /A mm=10%%a %% 100, dd=10%%b %% 100, yy=%%c
)
if %mm% lss 3 set /A mm=mm+12, yy=yy-1
set /A a=yy/100, b=a/4, c=2-a+b, e=36525*(yy+4716)/100, f=306*(mm+1)/10, jdn=c+dd+e+f-1523, dow=jdn %% 7 + 1
echo Today is !day[%dow%]!, %date%
Note that index values are not restricted to be numeric values as in other languages, but they may be any string that contain valid characters. Note also that the space is a valid character in variable names, so set a = 10
create "a " variable with " 10" value, so echo "%a%"
will show ""
and echo "%a %"
will show " 10"
.
I elaborated on the reasons I have to use array notation in Batch files at this post.
In this post there is a Batch file that read a text file and store the indexes of the lines in a vector, then do a Buble Sort of vector elements based on line contents; the equivalent result is a sort over file contents.
In this post there is a basic Relational Data Base application in Batch based on indexes stored in files.
In this post there is a complete multiple linked-list application in Batch that assemble a large data structure taken from a subdirectory and display it in the form of TREE command.