3

I've mentioned constant index in the title because all question in StackOverflow related to array indexing in a batch file were focused on accessing array using variable index inside a loop.

I'm new to batch scripting. I want to print array value with a constant index if the array is initialized as a list(in one line) rather than each element being initialized individually. I've written a snippet in which I can print the value of arr but not list.

@echo off
set arr[0]=1
set arr[1]=2
set arr[2]=3
set list=1 2 3 4
REM Result is 2
echo %arr[1]%
REM Won't print
echo %list[1]%
Mirwise Khan
  • 1,317
  • 17
  • 25

3 Answers3

0

A list in a string isn't an array, this answer 2 days ago shows how to turn a string list into an array.

To have the array index zero based use this changed version

:: SO_51225079.cmd
@echo off & Setlocal EnableDelayedExpansion
set arr[0]=1
set arr[1]=2
set arr[2]=3
set i=-1&set "list= 1 2 3 4"
Set "list=%list: ="&Set /a i+=1&Set "list[!i!]=%"
set list

REM Result is 2
echo %arr[1]%
REM Won't print
echo %list[1]%

Sample output:

> SO_51225079.cmd
list[0]=1
list[1]=2
list[2]=3
list[3]=4
2
2
0

You might be confusing Batch and PowerShell. In PowerShell, yes, you can initialize an array on one line:

$list = 1, 2, 3, 4
$list[1]
# output here would be 2

In the Batch scripting language, there are no array objects. You can simulate arrays by having similarly or sequentially named scalar variables, but the Batch language doesn't provide methods such as split() or splice() or push() or similar.

Often in Batch, splitting a string on spaces (or commas or semicolons) is accomplished by tokenizing using a for loop.

@echo off & setlocal

rem // Quoting "varname=val" is the safest way to set a scalar variable
set "list=1 2 3 4"

rem // When performing arithmetic using "set /a", spacing is more flexible.
set /a ubound = -1

rem // Split %list% by tokenizing using a for loop
for %%I in (%list%) do (
    set /a ubound += 1

    rem // Use "call set... %%ubound%%" to avoid evaluating %ubound% prematurely.
    rem // Otherwise, %ubound% is expanded when the for loop is reached and keeps the
    rem // same value on every loop iteration.
    call set "arr[%%ubound%%]=%%~I"
)

rem // output results
set arr[

setlocal enabledelayedexpansion
rem // You can also loop from 0..%ubound% using for /L
for /L %%I in (0, 1, %ubound%) do echo Element %%I: !arr[%%I]!
endlocal

As a side note, in that code block I demonstrated two methods of delaying expansion of variables in Batch -- using call set and setlocal enabledelayedexpansion using exclamation marks where delayed retrieval is desired. There are times when it's useful to know both. The enabledelayedexpansion method is usually more readable / more easily maintained, but in some circumstances can clobber values where exclamation marks possibly exist (such as file names). For that reason, I try to avoid enabling delayed expansion for the entire script.


LotPings' answer is clever, but limited in application. The way it works is, using substring substitution it sets and evaluates the value of list to a string of commands (separated by &). Unfortunately, it destroys the value of %list% in the process, and it cannot handle values containing spaces or exclamation marks.

@echo off & setlocal

set "list="The quick brown" "fox jumps over" "the lazy dog!!!""
set /a ubound = -1

for %%I in (%list%) do (
    set /a ubound += 1
    call set "arr[%%ubound%%]=%%~I"
)

rem // output results
set arr[

The for method of splitting will correctly maintain quoted spaces.

rojo
  • 24,000
  • 5
  • 55
  • 101
0

Batch has only one type of variable: string.

An array and a list are very different things (and it is discussed, if those even exist in batch, but they can be emulated). In batch, a list isn't different elements, but just a single string, and an array isn't a single structure, but different independend variables.

Nevertheless, you can split a string (that looks like a list) by delimiters (space is a default delimter) with a for loop:

set list=a b c d
set element=2
for /f "tokens=%element%" %%a in ("%list%") do echo %%a

(Note: this is batch syntax. For use directly on command line, replace each %%a with %a)

Stephan
  • 53,940
  • 10
  • 58
  • 91