Nested variable name using EnableDelayedExpansion - batch-file

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.

Related

8 Variables in one line (Batch)

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.

How to return the value of a increasing variable in Batch file?

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

How to access to the value of an environment variable in other variable in batch file

this is my code :
SET JAVA_VERSION=%1
REM here lets assume the user enter a JAVA_7_HOME as an argument
#ECHO %JAVA_VERSION%
REM this print me JAVA_7_HOME because JAVA_7_HOME is STRING
REM Now I want to access to the value of environment variable JAVA_7_HOME so I done this :
if %%%JAVA_7_HOME%%% ==[]GOTO INDEFINED_VARIABLE
REM here I concatinate JAVA_7_HOME with % % at the left and at the right but doesn't works
I Do not Know how to access to the value of the environment variable JAVA_7_HOME.
Thank you at all.
CALL SET JAVA_VERSION=%%%1%%
The line will be parsed to
CALL SET JAVA_VERSION=%JAVA_7_HOME%
Now, the call command is executed and the line reparsed, and the final command executed is
SET JAVA_VERSION=C:\SomeWhere
Also, you can enable delayed expansion and do
SETLOCAL EnableDelayedExpansion
SET JAVA_VERSION=!%1!
I backed to this subject :), So your solution it works fine without a loop for but now I changed the concept and I have a variable called CONTEXT_VARAIABLE which contains some others names of environnements variables for example in my case is:
CONTEXT_VARAIABLE=JAVA_HOME;JBOSS_HOME
so now I loop from this variable CONTEXT_VARAIABLE to get each variable and do some treatement with it so my code here is:
setlocal EnableDelayedExpansion
FOR %%L IN (%SOLIFE_VERSION%) DO (
SET JAVA_JBOSS_HOME=%%%%L%%
#ECHO !JAVA_JBOSS_HOME!
)
here each time of the loop it prints me:
%JAVA_HOME%
%JBOSS_HOME%
and now my problem I want to access to these variables and if I use CALL SET it makes an error because I think we are not allowed to use CALL SET in loop for.
So please if you have an idea about this problem.
Thank you.

how to pass a string to a labes that contains special characters like % and !?

Example:
call :my_label %%my!my%%myfolder%%folder!folder%%
:my_label
set my_local_var=%1
echo %my_local_var%
And I see no way of intact putting this string as local variable, is there a way to enable delayed expansion on a single percent variable ? Or any other way to prevent resolving variables in string ?
It's not clear what you expect, but a general rule is to use call with references not with values, as some values can't be transported at all.
So you could use something like this.
setlocal EnableDelayedExpansion
set "myString=%%my^!%%folder^!folder"
call :my_label myString
exit /b
:my_label
set "temp=!%1!"
echo !temp!
exit /b

Batch File EnableDelayedExpansion and Variable Setting

I'm editing a batch file given to me and I'm not sure what the following line of code does:
set allKeys=%allKeys% !currentKey!
thanks!
It appends the run-time value of the variable currentkey after a space to the parse-time value of allkeys and assigns the result as the run-time value of allkeys - provided delayedexpansion is invoked. If delayedexpansion is not invoked, it appends the string !currentKey!, not the value of the variable currentkey.
Without any context information, we're guessing beyond that...
Here is an example in code to try.
allkeys is set outside the for in do loop.
Inside the for in do loop it is changed but as it uses %allkeys% the changes are not cumulative.
#echo off
setlocal enabledelayedexpansion
set allkeys=one
for %%a in (two three four five six) do (
set currentkey=%%a
set allKeys=%allKeys% !currentKey!
echo allkeys is now "!allkeys!"
)
echo allkeys is now "%allkeys%" outside the loop
pause
Change this line
set allKeys=%allKeys% !currentKey!
to this and run it to see the difference.
set allKeys=!allKeys! !currentKey!
For a decription of what delayed expansion is, type SET /?.

Resources