I have tried multiple things with a code like this.
#echo off
set %1%=A
set %2%=B
set %3%=C
set %4%=D
set %5%=E
set %6%=F
set %7%=G
set %8%=H
echo %1%%2%%3%%4%%5%%6%%7%%8%%9%
But kinda nothing worked, the output was this:
1%2%3%4%5%6%7%8
How do I get it to output ABCDEFGH?
Try with
#echo off
set _1=A
set _2=B
set _3=C
set _4=D
set _5=E
set _6=F
set _7=G
set _8=H
echo %_1%%_2%%_3%%_4%%_5%%_6%%_7%%_8%
Starting from the concept, your problem is that %n with n in the range 0..9 is handled by the batch parser as an command line argument to the batch file, not a variable expansion operation.
You can use number prefixed variable names, but then you will require to enable delayed expansion and change the variable expansion syntax from %varName% in to !varName! to be able to retrieve the value. It is easier not use number prefixed variables names.
The second problem is that the syntax %varName% is only used where the variable value needs to be retrieved. When you set the value, the syntax is set varName=varValue, or still better you can quote the operation as set "varName=varValue" to avoid problems with special characters and inclusion of unneeded ending spaces.
Your question is not clear. The code below do exactly what you requested:
#echo off
set A=A
set B=B
set C=C
set D=D
set E=E
set F=F
set G=G
set H=H
echo %A%%B%%C%%D%%E%%F%%G%%H%
However, is likely that this obvious solution is not what you are looking for...
If you want to know if is there a way to "automatically" define a series of variables and process they all, then the solution is to use an array. You may read the description of the array concept in this Wikipedia article and a detailed explanation of array management in Batch files at this answer. For example:
#echo off
setlocal EnableDelayedExpansion
rem Create "a" array with all elements given:
set n=0
for %%a in (A B C D E F G H) do (
set /A n=n+1
set a[!n!]=%%a
)
rem Show the 8 elements of "a" array
echo %a[1]%%a[2]%%a[3]%%a[4]%%a[5]%%a[6]%%a[7]%%a[8]%
rem Join *all* the elements of "a" array in a single variable
set "all="
for /L %%i in (1,1,%n%) do set "all=!all!!a[%%i]!"
echo %all%
Note that the last example works correctly no matters how many elements have been defined in "a" array.
Although you may also write the array elements in a shorter way, ommiting the braquets: set "a1=A" & set "a2=B", etc, and then use echo %a1%%a2%..., you should remember that the use of braquets is a standard notation used in many other programming languages, so it is convenient to keep it.
Related
I am setting up some code that will help me run a mathematical experiment. Is there a way to use loops in batch to create multiple variables automatically.
I have tried to join a variable to a set command (before the equal sign), but then the command does not run.
#echo off
set variablerep=0
pause
Set p1=0
Set p2=0
Set p3=0
...
...
Set p34=0
Set p35=0
Set p36=0
Pause
I hope to find ways by which I don't need to copy each set command and make minor changes and code efficiently.
Use for /l loop:
#echo off
setlocal
set p_
for /l %%l in ( 1, 1, 36 ) do set p_%%l=0
set p_
Please remember that math in (pure) batch is restricted to 32bit signed integers (+/- ~2GB).
and NO floating point math.
All variables are stored as strings and only set /A and the if commands try to convert to integers.
the syntax of set /a allows several calculatons on one line delimited with a comma,
set /A p1=0,p2=0,p3=0
there also is a special variant allowing to set several variables to the same value:
set /A p1=p2=p3=0
When using an index to address variables the pseudo array[%%I] format is common, whereas every valid naming scheme can be used - as jsxts answer shows.
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]%
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
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.
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)
I have a very long string for use as a map. It is about 50 characters (10 for my example though). I also have a string that I want to use as a number that represents the players position on the map string:
#ECHO OFF
SET map=CGWGWBBBTB
SET playerposition=1
So if playerposition was 3 I would want to receive W from this next line of code:
%map:~%playerposition%,1%
It seems I can not retrieve the playereposition variable like that.
#ECHO OFF
SETLOCAL
#ECHO OFF
SET map=CGWGWBBBTB
SET playerposition=1
CALL SET playereposition=%%map:~%playerposition%,1%%
SET play
SET playerposition=2
CALL SET playereposition=%%map:~%playerposition%,1%%
SET play
SET playerposition=3
CALL SET playereposition=%%map:~%playerposition%,1%%
SET play
You could also use a subroutine:
SET playerposition=4
CALL :setsubstr playereposition map %playerposition% 1
SET play
GOTO :EOF
:setsubstr
SETLOCAL ENABLEDELAYEDEXPANSION
SET "return=!%2:~%3,%4!"
endlocal&SET "%1=%return%"
GOTO :EOF
Here, the temporary variable return is used to contain the substring-from-3rd-parameter-length-4th-parameter-of the string second-parameter into variable-name first-parameter.
The endlocal&... disposes of the temporary variable and uses a parsing trick to assign the value to %1.
Note that using this approach also allows the routine to be made "smart" by allowing (with changes) an omitted 4th parameter to default to 1, for instance.
Note also in all of this that position-counting in a string starts from 0, not 1.
As you can see in my script bellow, the %pin%count%% (maybe obviously for some of you) won't return the wanted value but the string value of the wanted variable, as %pin5% for instance.
I've created a script where the number of variables will depend on how many colors the user chose for his pins. The troubling part of the script is:
Echo - Please type the colors of the pins allowed in the purchase,
or type dot (.) to finish this part of the script.
set count=0
:Pin
set /a count=%count%+1
set /p pin%count%=
if not %pin%count%%=="." goto Pin
I cannot use the IF statement because %pin%count%% returns %pin1% or %pin2% but not the value itself, how to solve this?
It seems like a simple enough syntax problem, but i'm trying everything and haven't managed to solve it yet and asking may be the fastest solution.
to evaluate a composite variable name, you have to use setlocal enabledelayedexpansion so you can specify ! as an extra delimiter,
The other problem you had is that you compared the variable with ".". Batch does not remove quotes like bash does. Don't put the quotes, or put some quotes on the left end too.
Fixed code:
#echo off
Echo - Please type the colors of the pins allowed in the purchase,
echo or type dot (.) to finish this part of the script.
setlocal enabledelayedexpansion
set count=0
:Pin
set /a count+=1
set /p pin%count%=
rem echo the variable for debug purposes
echo pin%count% = !pin%count%!
rem here's the tricky line
if not !pin%count%!==. goto Pin
I am working on a script to get max lengths of each column, I'm trying to store lengths of max length in _c1...n vars. number of columns unknown.
I was able to get length for each column, create variables to store each with set _c!i! = !n!, n is the length
but in order to set the max length for a particular column I need to compare current with max and use something like !_c!!i!! which doesn't work, any ideas how to refer a variable which part of it's name coming from another variable?
Thanks...
I assume that you are using the delayed expansion character because you are working inside a set of brackets "()". Doing that makes your process harder. I know that method is easier to read, but it is harder to code for.
Inside brackets, I know of only one method to access a variable that was 'built' out of one or more variables. That is to use the call function to cause the assembled variable to 'activate'. This method works both inside and outside of brackets.
Here is a small example:
#echo off
setlocal enabledelayedexpansion
(
set i=10
set _c!i!=something
:: below is equivalent to echo !_c10!
call echo %%_c!i!%%
)
endlocal
Output:
something
You can do almost everything using a CALL in front of it that you can without it, though in XP or earlier you cannot call internal commands like if and can only call 'external' programs like FIND.EXE.
If you can work outside of a set of brackets by possibly using a call :label statement, you can simply access the variable like this:
#echo off
setlocal enabledelayedexpansion
set i=10
set _c!i!=something
:: The below 2 statements are equivalent to `echo %_c10%`
echo !_c%i%!
call echo %%_c!i!%%
endlocal
Output:
something
something
The CALL technique suggested by James K will work, but it is relatively slow and can be unsafe, depending on the content of the variable.
The following looks more complicated, but it is significantly faster and more reliable:
for %%A in (!i!) do echo !_c%%A!
In your case there could be a third solution be possible, if your variables contains only numbers.
#echo off
setlocal enabledelayedexpansion
(
set i=10
set _c!i!=4711
set /a tmp=_c!i!
echo !tmp!
)
This works, as SET /A can access the content of a variable without the nedd of explicitly expansion charaters.