Difficulty Comparing a variable substring to a string - batch-file

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.

Related

How to squeeze lots of variables?

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.

Batch File - How to get the value of an array with variable index?

I'm trying to set a variable with the value from an array in a batch file, but no solution seems to work so far. Here's a snippet of the situation:
:: random value
set ParId=123
:: get the last number of the previous value
set /a "temp0=%ParId% %% 10"
:: part of my array, just for the example
set AsciiNumTable[0]=0x30
set AsciiNumTable[1]=0x31
set AsciiNumTable[2]=0x32
set AsciiNumTable[3]=0x33
set AsciiNumTable[4]=0x34
set AsciiNumTable[5]=0x35
set AsciiNumTable[6]=0x36
set AsciiNumTable[7]=0x37
set AsciiNumTable[8]=0x38
set AsciiNumTable[9]=0x39
:: PART NOT WORKING
set ParIdByte0=AsciiNumTable[%temp0%]
I've tried different methods:
call set ParIdByte0=%AsciiNumTable[!tempId5!]%
but they also do not work.
If I output the array and the temp variable they look fine, so I don't know why I can't get the value from the array.
It can be done in a reverse approach you are trying (with using delayed expansion).THough there are few more issues with your script 1)Missing set keyword when assigning value to ParId 2) temp0 value will be 3 and you have no third element in the array:
#echo off
setlocal enableDelayedExpansion
:: random value
set ParId=123
:: get the last number of the previous value
set /a "temp0=%ParId% %% 10"
:: part of my array, just for the example
set AsciiNumTable[0]=0x30
set AsciiNumTable[1]=0x31
set AsciiNumTable[2]=0x32
set AsciiNumTable[3]=0x33
:: PART NOT WORKING
set ParIdByte0=!AsciiNumTable[%temp0%]!
echo --%ParIdByte0%--
"do not work" is meaningless. Please state what you expect and what actually happened.
Try
call set ParIdByte0=%%AsciiNumTable[%temp0%]%%

get last 2 tokens from a variable in Batch

i need to get the last 2 tokens from a variable in Batch
the variable is
Rastreando a rota para user722-PC [192.168.1.106]
the output i need is a variable containing
user722-PC
and another containing
[192.168.1.106]
and no, i cant use
for /f "tokens=5,6 delims= " %%a in ("%variable%") do set host=%%a & set ip=%%b
echo %ip% %host%
because in this case i specified tokens 5,6 and what i want to to is to get the last 2 tokens dynamicaly, so i must NOT specify any token numbers mannualy
// this way i can get only the last token, considering that the delimiter is a space, and the delimiter cant be changed
FOR %%a in (%variable%) do set lastPart=%%a
ECHO %lastPart%
#echo off
setlocal EnableDelayedExpansion
set "var=Rastreando a rota para user722-PC [192.168.1.106]"
set "last=%var: =" & set "lastBut1=!last!" & set "last=%"
SET last
Hint: run this program with #echo on
#ECHO OFF
SETLOCAL
SET "variable=Rastreando a rota para user722-PC [192.168.1.106]"
FOR %%a IN (%variable%) DO CALL SET "lastbut1=%%lastpart%%"&SET "lastpart=%%a"
SET last
GOTO :EOF
calling the set re-parses it, so set "lastbut1=%lastpart%" is executed in a subshell.
This could also be done using delayedexpansion about which there are many articles on SO.
The short explanation for how it works is *** MAGIC ***
A longer explanation is this:
the commands CALL SET "lastbut1=%%lastpart%%" and SET "lastpart=%%a" are executed in that sequence for each element in %variable% which is a simple string with elements separated by spaces, tabs, commas or semicolons.
The & is used to separate the commands and serves merely to allow many commands to be specified on he same physical line. The code could also be written
(
CALL SET "lastbut1=%%lastpart%%"
SET "lastpart=%%a"
)
which is exactly the same; the parentheses are required and enclose the individual commands. There an additional syntax-requirement here. The opening ( must be on the same physical line as the do.
The CALL SET "lastbut1=%%lastpart%%" executes SET "lastbut1=%lastpart%" in a sub-shell, setting lastbut1 to the current value of lastpart. Then the SET "lastpart=%%a" sets lastpart to the value in %%a.
So, on the next iteration, lastbut1 gets the value that was applied to lastpart in the prior iteration, and so on until the very last time, when lastpat acquires the very last item on the list and lastbut1 has just been assigned the value just before that.
Hence, to get lastbut2, all you'd need would be to use
FOR %%a IN (%variable%) DO call set "lastbut2=%%lastbut1%%&CALL SET "lastbut1=%%lastpart%%"&SET "lastpart=%%a"
which sets lastbut2 from lastbut1, lastbut1 from lastpart and lastpart from %%a in that sequence.

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.

Nested variable name using EnableDelayedExpansion

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.

Resources