I'm being driven crazy by a stupidly simple problem that is eating up my time. I just want to append strings separated by comma, but the comma doesn't get appended. Below is my batch file snippet:
set MissingParams=
set SwitchURL=
set TrustStore=
if 0%SwitchURL%==0 (set MissingParams=SwitchURL)
if 0%TrustStore%==0 (
if not 0%MissingParams%==0 (
set MissingParams=%MissingParams%,
)
set MissingParams=%MissingParams%TrustStore
)
After runnin this script when I echo %MisingParams%, the expected value is SwitchURL,TrustStore but it simply prints
SwitchURLTrustStore.
D:\deleteme>echo %MissingParams%
SwitchURLTrustStore
For debugging, when I introduced some echo statements in the batch file, the results are even more bizzare:
set MissingParams=
if 0%SwitchURL%==0 (set MissingParams=SwitchURL)
if 0%TrustStore%==0 (
if not 0%MissingParams%==0 (
echo MissingParams=%MissingParams%
set MissingParams=%MissingParams%,
echo MissingParams=%MissingParams%
)
set MissingParams=%MissingParams%TrustStore
echo MissingParams=%MissingParams%
)
When I run the above script it prints
MissingParams=SwitchURL
MissingParams=SwitchURL
MissingParams=SwitchURL
And when I echo the value from the command prompt, as before I get SwitchURLTrustStore
D:\deleteme>echo %MissingParams%
SwitchURLTrustStore
Does anyone have any ideas? This is frustrating me to no end.
This is the standard parenthesis/delayedExpansion problem.
The simple rule is %var% are expanded before a parenthesis block is executed(while parsing).
If you need the var-expansion later, you should use the delayed expansion.
Explained in set /?
setlocal EnableDelayedExpansion
set MissingParams=
set SwitchURL=
set TrustStore=
if 0!SwitchURL!==0 (set MissingParams=SwitchURL)
if 0!TrustStore!==0 (
if not 0!MissingParams!==0 (
set MissingParams=!MissingParams!,
)
set MissingParams=!MissingParams!TrustStore
)
Sort of looks like a scoping problem. I was able to work around this by branching with a goto which works. Here's my version with extra debug crap:
#echo off
set MissingParams=
set SwitchURL=
set TrustStore=
if "%SwitchURL%"=="" (set MissingParams=SwitchURL)
echo MissingParams1 is %MissingParams%
if "%TrustStore%" EQU "" (GOTO :BRANCH1)
:RESUME
echo MissingParams3 is %MissingParams%
set MissingParams=%MissingParams%TrustStore
echo MissingParams4 is %MissingParams%
)
echo MissingParamsF is %MissingParams%
GOTO :eof
:BRANCH1
if "%MissingParams%" NEQ "" (set MissingParams=%MissingParams%,)
GOTO RESUME
Related
I come to find some guidance on accomplishing the following:
I have a variable with content like this:
varname = asdfiuytgy12$gggsy22.oihbcxew
or
varname = oiujedc$thisisit.oiju
which $ and . are exactly my partters and I need to get what is within them so gggsy22 or thisisit.
I need to use batch to create a simple bat file. I hope someone can provide some guidance.
Edit - (from comment section)
Actually a friend of mine helped and it did work but with a quite amount of lines:
Set "sstr=$"
SET stemp=%nameVar%&SET pos=0
:loop
SET /a pos+=1
echo %stemp%|FINDSTR /b /c:"%sstr%" >NUL
IF ERRORLEVEL 1 (
SET stemp=%stemp:~1%
IF DEFINED stemp GOTO loop
SET pos=0
)
Set "pos1=%pos%"
Set "sstr=."
SET stemp=%nameVar%&SET pos=0
:loop
SET /a pos+=1
echo %stemp%|FINDSTR /b /c:"%sstr%" >NUL
IF ERRORLEVEL 1 (
SET stemp=%stemp:~1%
IF DEFINED stemp GOTO loop
SET pos=0
)
Set "pos2=%pos%"
set /a "pos2=%pos2%-%pos1%-1"
call set env=%%nameVar:~%pos1%,%pos2%%%
#echo off
set "varname=asdfiuytgy12$gggsy22.oihbcxew"
for /f "tokens=2 delims=$." %%a in ("%varname%") do set "sub=%%a"
The following works in nearly any situation. The only thing that could break the code is if the string contains a quote " followed by a poison character like &, |, etc.
#echo off
setlocal
set "str=oiujedc$thisisit.oiju"
:: Verify string exists and has the proper format
echo "%str%"|findstr "\$.*\." >nul || (echo Value not found & exit /b)
:: Extract the value
:: The extra "x" is needed in case there is no character between $ and .,
:: in which case the result should be No Value (result variable not defined)
for /f "delims=." %%A in ("x%str:*$=%") do set "val=%%A"
set "val=%val:~1%"
:: Show the result
echo value = "%val%"
A bullet proof variant can be made by incorporating delayed expansion.
(set /a "m1=1,m2=2")
for /f %%c in ("%m1%%m2%") do echo %%c
pause
The brackets else where than due to the for command are used in cases, a space key should have been added.
The echo of the for command, is 12. I used the number characters to face the set /A command with decimal Expression.
When i try the same procedure only with a set for a Shell, may also be named m1 it is just possible without comma seperation.
With set command the m1 Expression would be 1 m2 2 and not two values like with a set /A SET.
Is there a way to use set only once and not only with the set /A?
As other answers and comments already indicated, there is no way to directly do this in one command, but via a procedure. The method below is the simplest one:
#echo off
rem Define the several values
set "vars=m1=1,m2=2"
rem Do it:
set "%vars:,=" & set "%"
echo m1=%m1%
echo m2=%m2%
You may remove the #echo off command and execute this program to see what exactly is executed...
As I understand the question you want something like:
set x=1,y=2
and as a result to have two variables (like set /a). The answer is no.
Though you can iterate trough expressions with plain for :
#echo off
for %%a in (
"x=1" "a=5"
"y=2" "b=6"
"z=3" "c=7"
) do set "%%~a"
echo %x% %y% %z% %a% %b% %c%
Mind that the quotes around the items are mandatory because = is a delimiter. You can put everything on line and to use as separators , ,; ,<space>
May be with a lot of variables this can save you from some writing...?
this can be rewritten like this:
#echo off
set "vars=x=1,y=2,z=3,a=5,b=6,c=7"
for %%a in ("%vars:,=","%") do set "%%~a"
echo %x% %y% %z% %a% %b% %c%
And thus you'll need to change only the vars value.
so I'm writing batch and come up with the ( was unexpected error after setting the first variable. I want a batch file to start with just setting the color. (I named it edmond)
this is my code
#echo off
SETLOCAL
title Edmond
goto :Check
:Prompt
set /p action=What shall I do for you master?
:Check
if not defined action goto :Prompt
echo %action%
pause
if /i %%action == color (
echo stuff
:cl
set /p BC=What Should the background color be?
set /p FC=and the foreground color?
if %BC%==Black set BC1=0
if %BC%==Blue set BC1=1
if %BC%==Green set BC1=2
if %BC%==Aqua set BC1=3
if %BC%==Red set BC1=4
if %BC%==Purple set BC1=5
if %BC%==Yellow set BC1=6
if %BC%==White set BC1=7
if %BC%==Gray set BC1=8
if %BC%==LBlue set BC1=9
if %BC%==LGreen set BC1=a
if %BC%==LAqua set BC1=b
if %BC%==LRed set BC1=c
if %BC%==LPurple set BC1=d
if %BC%==LYellow set BC1=e
if %BC%==LWhite (
set BC1=f
) else (
echo I'm sorry, I didn't exactly understand that.
echo By any chance could you say it again?
goto cl
)
if %FC%==Black set FC1=0
if %FC%==Blue set FC1=1
if %FC%==Green set FC1=2
if %FC%==Aqua set FC1=3
if %FC%==Red set FC1=4
if %FC%==Purple set FC1=5
if %FC%==Yellow set FC1=6
if %FC%==White set FC1=7
if %FC%==Gray set FC1=8
if %FC%==LBlue set FC1=9
if %FC%==LGreen set FC1=a
if %FC%==LAqua set FC1=b
if %FC%==LRed set FC1=c
if %FC%==LPurple set FC1=d
if %FC%==LYellow set FC1=e
if %FC%==LWhite (
set FC1=f
) else (
echo I'm sorry, I didn't exactly understand that.
)
echo Applying changes.
ping localhost -n 2 >nul
color %FC%%BC%
) else (
echo I'm sorry, I didn't exactly understand that.
)
pause
exit
after the set /p action=what shall I do for you master? it says ( was unexpected and then shuts down (I got the ( was unexpected by printing screen before it closes) can someone help? thanks (in advance)
if /i %%action == color (
should be
if /i %action% == color (
or better
if /i "%action%"=="color" (
since you have uncontrolled input that may contain spaces or other separators.
Your upcoming problems are many-fold.
You can't use a label in a (block statement - a series of parenthesised statements)
You need to
setlocal enabledelayedexpansion
then use !var! in place of %var% withing a block statement to access the value of any ordinary environment variable changed or established within the block.
Very much truncated revised structure:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
:Prompt
set /p action=What shall I do for you master?
:Check
if not defined action goto :Prompt
echo %action%
if /i "%action%"=="color" GOTO setcolor
echo I'm sorry, I didn't exactly understand that.
goto Prompt
:setcolor
echo stuff
:cl
set /p BC=What Should the background color be?
set /p FC=and the foreground color?
:: This forces BC1 & FC1 to be undefined
SET "BC1="
SET "FC1="
if /i "%BC%"=="Black" set BC1=0
if /i "%BC%"=="Blue" set BC1=1
:: Your job to fill in the rest
IF NOT DEFINED BC1 (
echo I'm sorry, I didn't exactly understand that.
echo By any chance could you say it again?
goto cl
)
if /i "%FC%"=="Yellow" set FC1=6
:: Your job to fill in the rest
IF NOT DEFINED BC1 (
echo I'm sorry, I didn't exactly understand that.
rem I suppose you really want to re-enter at this point.
rem note that you need to use REM within a block, not ::-style comments.
goto cl
)
echo Applying changes.
ping localhost -n 2 >NUL
:: Best to use FC1 and BC1 here, else you'll try to execute "color YellowBlack"
:: And it's likely you have them reversed.
color %FC1%%BC1%
GOTO :EOF
I was trying to open a folder on every lab computer using a batch script. The computers are labeled 01,02,03-18. I didn't think there was a way to convert the number from 1 to 01 so I used an if statement. But I am getting an error that says 9 was unexpected at this time
#echo off
setlocal enabledelayedexpansion
SET "z=0"
SET "n=9"
for /L %%x in (1,1,18) do (
SET v=%%x
IF %v% LEQ %n%
(
SET num=%z%%v%
) ELSE (
SET num=%v%
)
start "" "\\lab-!num!\
pause
)
You have problems with the placement of th parenthesis (see here), and an inconsistent usage of the delayed expansion (you are using !num! but not !v!, the two variables that change inside the code block) but the code can be simplified by including the padding in the values of the for loop
for /l %%x in (1001, 1, 1018) do (
set "num=%%x"
start "" "\\lab-!num:~-2!\share\folder"
)
When delayed expansion is enabled, use exclamation marks inside for loops.
And don't forget that open parenthesis must be on the same line as the if
#echo off
setlocal enabledelayedexpansion
SET "z=0"
SET "n=9"
for /L %%x in (1,1,3) do (
SET v=%%x
IF !v! LEQ !n! (
SET num=!z!!v!
) ELSE (
SET num=!v!
)
start \\lab-!num!\
pause
)
I've a text file with two rows (say param.txt) which is shown below:
Mar2012
dim1,dim2,dim3,dim4
I want to read this file in batch and store the contents of first line in a variable called cube_name. When I'm reading the second line, I want to split the comma delimited string dim1,dim2,dim3,dim4 and create an array of four elements. I am planning to use the variable and the array in later part of the script.
The code which I created is shown below. The code is not working as expected.
#echo off & setlocal enableextensions enabledelayedexpansion
set /a count_=0
for /f "tokens=*" %%a in ('type param.txt') do (
set /a count_+=1
set my_arr[!count_!]=%%a
)
set /a count=0
for %%i in (%my_arr%) do (
set /a count+=1
if !count! EQU 1 (
set cube_name=%%i
)
if !count! GTR 1 (
set dim_arr=%%i:#=,%
)
)
for %%i in (%dim_arr%) do (
echo %%i
)
echo !cube_name!
I get to see the following when I run the code:
C:\Working folder>test2.bat
ECHO is off.
So this doesn't appear to work and I can't figure out what I'm doing wrong. I am fairly new to the batch scripting so help is appreciated
Your first FOR loop is OK. It is not how I would do it, but it works. Everything after that is a mess. It looks like you think arrays are a formal concept in batch, when they are not. It is possible to work with variables in a way that looks reminiscent of arrays. But true arrays do not exist within batch.
You use %my_arr% as if it is an array, but my_arr is not even defined. You have defined variables my_arr[1] amd my_arr[2] - the brackets and number are part of the variable name.
It also looks like you have a misunderstanding of FOR loops. I suggest you carefully read the FOR documentation (type HELP FOR from a command line). Also look at examples on this and other sites. The FOR command is very complicated because it has many variations that look similar to the untrained eye, yet have profoundly different behaviors. One excellent resource to help your understanding is http://judago.webs.com/batchforloops.htm
Assuming the file always has exactly 2 lines, I would solve your problem like so
#echo off
setlocal enableDelayedExpansion
set dimCnt=0
<param.txt (
set /p "cube_name=" >nul
set /p "dimList=" >nul
for %%D in (!dimList!) do (
set /a dimCnt+=1
set "dim[!dimCnt!]=%%D"
)
)
echo cube_name=!cube_name!
for /l %%I in (1 1 !dimCnt!) do echo dim[%%I]=!dim[%%I]!
One nice feature of the above solution is it allows for a varying number of terms in the list of dimensions in the 2nd line. It will fail if there are tabs, spaces, semicolon, equal, * or ? in the dimension names. There are relatively simple ways to get around this limitation if need be.
Tabs, spaces, semicolon and equal can be handled by using search and replace to enclose each term in quotes.
for %%D in ("!dimList:,=","!") do (
set /a dimCnt+=1
set "dim[!dimCnt!]=%%~D"
)
I won't post the full solution here since it is not likely to be needed. But handling * and/or ? would require replacing the commas with a new-line character and switching to a FOR /F statement.
I'm impressed of your code!
Do you try to debug or echo anything there?
You could simply add some echo's to see why your code can't work.
#echo off & setlocal enableextensions enabledelayedexpansion
set /a count_=0
for /f "tokens=*" %%a in ('type param.txt') do (
set /a count_+=1
set my_arr[!count_!]=%%a
)
echo ### show the variable(s) beginning with my_arr...
set my_arr
echo Part 2----
set /a count=0
echo The value of my_arr is "%my_arr%"
for %%i in (%my_arr%) do (
set /a count+=1
echo ## Count=!count!, content is %%i
if !count! EQU 1 (
set cube_name=%%i
)
if !count! GTR 1 (
echo ## Setting dim_arr to "%%i:#=,%"
set dim_arr=%%i:#=,%
echo
)
)
for %%i in (%dim_arr%) do (
echo the value of dim_arr is "%%i"
)
echo cube_name is "!cube_name!"
Output is
### show the variable(s) beginning with my_arr...
my_arr[1]=Mar2012
my_arr[2]=dim1,dim2,dim3,dim4
Part 2----
The value of my_arr is ""
cube_name is ""
As you can see your part2 fails completly.