I would like to print the following:
0
1
2
3
4
I have tried this:
ECHO OFF
FOR /L %%A in (1,1,5) DO (
SET /a "B=%%A-1"
ECHO %B%
)
However, this gives me:
4
4
4
4
4
How can I achieve the desired output while using both A and B in my code?
ECHO OFF
setlocal
FOR /L %%A in (1,1,5) DO (
SET /a "B=%%A-1"
call ECHO %%B%%
)
Since you are not using setlocal, B will be set to the value from the previous run. %B% will be replaced by 4 since B was set to 4 by the previous run. the call echo trick uses a parsing quirk to retrieve the current (run-time) value of the variable.
Here's "the official" way:
ECHO OFF
setlocal enabledelayedexpansion
FOR /L %%A in (1,1,5) DO (
SET /a "B=%%A-1"
ECHO !B!
)
In delayedexpansion mode, !var! retrieves the value of var as it changes at run-time. This is not without its drawbacks, but you'd need to read up on delayedexpansion for a guide on that matter.
Related
For the record, seeing that this type of questions is pretty popular on SO, I read around 30 answers in SO and couldn't find a question and answer that fit perfectly to my needs.
I have the following snippet:
#echo off
setlocal EnableDelayedExpansion
set string=test
for /l %%l in (0,1,1) do (
set /A remainder=%%l %%2
if remainder equ 1 (
set /A curr=%%l+1
call set res=!string:~-%curr%,1!
echo !res!
)
)
When executed this way, I get:
string:~-curr
How do I get the line with the variable substring with variable range - call set res=!string:~-%curr%,1!, to execute properly? For instance, for the second index (1), I want it to execute as if set res=!string:~-2,1! is written there.
How do I solve this?
You cannot use normal (immediate) expansion for the variable curr since you write and read it in the same block of code. However, since nested delayed expansion (like !string:~-!curr!,1!) does not work (because !string:~-! and !,1! were seen as variables then, and the former was even invalid syntax), you could use an interim for loop:
#echo off
setlocal EnableDelayedExpansion
set "string=test"
for /L %%l in (0,1,1) do (
set /A "remainder=%%l%%2"
if !remainder! equ 1 (
set /A "curr=%%l+1"
for %%k in (!curr!) do (
set "res=!string:~-%%k,1!"
echo(!res!
)
)
)
endlocal
(I prefer this over the approach call set "res=%%string:~-!curr!,1%%", because call may introduce trouble with the caret symbol ^ and it is slower.)
I have no idea, what your code is supposed to do, but to clear the error you mention:
#echo off
setlocal EnableDelayedExpansion
set string=test
for /l %%l in (0,1,1) do (
set /A remainder=%%l %%2
if !remainder! equ 1 (
set /A curr=%%l+1
call set res=%%string:~-!curr!,1%%
echo !res!
)
)
I'd like to write a batch file which will display numbers from 1 to 5.
Here is my code:
#ECHO OFF
FOR /l %%A in (1,1,5) do (
SET number=%%A
ECHO %number%
)
And here is an output:
5
5
5
5
5
What is wrong with my code?
You are missing ENABLEDELAYEDEXPANSION and !number! instead of %number%.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /l %%A in (1,1,5) DO (
SET number=%%A
ECHO !number!
)
When variables are changed inside loop or if structures you always have to work with ENABLEDELAYEDEXPANSION and access the variables as !var! instead of %var%.
I want to be able to get the next argument to compare to the current argument. So when the argVec is equal to "--define", I want to echo the next argument. I get the result "y" instead of "delivery".
My input is:
Cmd version version1 --define delivery
set inputArg=%*
setlocal enabledelayedexpansion
set Count=0
for %%x in (%inputArg%) do (
set /A Count+=1
set "argVec[!Count!]=%%~x"
)
for /L %%i in (1,1,%Count%) do echo %%i- !argVec[%%i]!
for /L %%x in (1,1,%Count%) do (
set /A y=%%x+1
#echo !y!
#echo !argVec[%%x]!
if "!argVec[%%x]!"=="--define" (
#echo !argVec[!y!]!
)
)
endlocal
When I added #echo off to the top of your script and ran it, I got the following output:
1- version1
2- --define
3- delivery
2
version1
3
--define
y
4
delivery
If I understand you correctly, the problem is the y on the third line from the bottom.
The reason you are getting y is because of #echo !argVec[!y!]!. This tokenizes as #echo, !argVec[!, y, !]!, which means "echo the contents of the !argVec[! variable, then echo y, then echo the contents of the ] variable. Since you don't have an !argVec[! variable or a ] variable, this reduces to "echo y".
To fix it, there is lots of good information at this SO answer. For your purposes, the important part of that post is this:
To get the value of an element when the index change inside FOR/IF enclose the element in double percents and precede the command with call.
Here is a version of your script that I think does what you want it to do:
#echo off
set inputArg=%*
setlocal enabledelayedexpansion
set Count=0
for %%x in (%inputArg%) do (
set /A Count+=1
set "argVec[!Count!]=%%~x"
)
for /L %%i in (1,1,%Count%) do echo %%i- !argVec[%%i]!
for /L %%x in (1,1,%Count%) do (
set /A y=%%x+1
#echo !y!
#echo !argVec[%%x]!
if "!argVec[%%x]!"=="--define" (
#call echo %%argVec[!y!]%%
)
)
endlocal
That prints:
1- version1
2- --define
3- delivery
2
version1
3
--define
delivery
4
delivery
I realize that echoing to the screen is probably not your final goal, so when you modify the script to do what you really want it to do, remember to use double percents around the whole "array", exclamation points around the index, and precede your command with call.
For example, if you want to add a compare condition, then set the contents of argVec[y] to a temporary variable from a call, and then use the temporary variable in your if, like this:
#echo off
set inputArg=%*
setlocal enabledelayedexpansion
set Count=0
for %%x in (%inputArg%) do (
set /A Count+=1
set "argVec[!Count!]=%%~x"
)
for /L %%i in (1,1,%Count%) do echo %%i- !argVec[%%i]!
for /L %%x in (1,1,%Count%) do (
set /A y=%%x+1
#echo !y!
#echo !argVec[%%x]!
#call set tmpvar=%%argVec[!y!]%%
if "!tmpvar!"=="--define" (
echo "found it"
)
)
endlocal
Output of the latest:
1- version1
2- --define
3- delivery
2
version1
"found it"
3
--define
4
delivery
You can not "nest" delayed expansions this way:
#echo !argVec[!y!]!
There are several ways to solve this problem, that are described here; the most efficient one is this:
for %%y in (!y!) do #echo !argVec[%%y]!
EDIT: Additional request stated in comment solved.
You may use the same method to get the value of argVec[!y!] and use it in any way you wish. For example:
for %%y in (!y!) do if "!argVec[%%y]!"=="delivery" echo true1
Here's the little bit of code I have:
if %a%==1 set /a count=%count%+%random% %%100
What it does (at the moment) is simply stay as %count% and not increase by a random number between 1 and 100.
What I want it to do is this:
If a is equal to 1 (which it always is in an earlier line of code) it will increase count by a random number between 0 and 99. If anyone could help, that would be great! (It's my first time on stackoverflow and I'm new at programming so make it simple!)
I'm not sure what your problem is? Have you posted your full script? The following script works for me.
#echo off
setlocal
set a=1
set count=0
echo count: %count%
if %a% == 1 set /a count=%count%+%random% %%100
echo count: %count%
As MC ND points out you may have problems if you're using count inside another block (e.g., inside a for-loop). The following does not work.
#echo off
setlocal
set a=1
set count=0
for /L %%x in (1,1,1) do (
if %a% == 1 set /a count=%count%+%random% %%100
rem This always prints 0!
echo count: %count%
)
To get it working use setlocal enableDelayedExpansion. The following is again working.
#echo off
setlocal enableDelayedExpansion
set a=1
set count=0
for /L %%x in (1,1,1) do (
if !a! == 1 set /a count=!count!+%random% %%100
rem Now this works!
echo count: !count!
)
I am new in batch. Trying for some days to make something in batch but have a problem I cannot solve. I read a lot of your comments but did not find answer. Maybe you can help me?
The point is:
I input string from keyboard( e.g. 10 characters ). name of it is"allinputstring"
Calculate of length is ok ( by redirect in txt file and expand its bytes ). name "length"
Parse string in 10 pieces (strings) is ok.
So here is a problem, I want to echo these pieces, so I use next code, I use a counter to find out is the counter give me good count as output variable, and echo it to see on screen if it is good. Counter seems good, end echo of pieces strings is good enough. But I want to put in line 5. Variable count instead of "%%m", and cannot find a syntax way how to do it.
setlocal enabledelayedexpansion
for /l %%m in (1,1,!lenght!) do (
set /a count=0
set /a count=count+%%m
echo !count!!allinputstring:~%%m,1!
)
endlocal
please help me.
Try this:
#echo off &setlocal enabledelayedexpansion
set /a lenght=9
set "allinputstring=ABCDEFGHIJ"
for /l %%m in (0,1,%lenght%) do (
set /a count=0
set /a count+=%%m
echo !count! !allinputstring:~%%m,1!
)
endlocal
Output is:
0 A
1 B
2 C
3 D
4 E
5 F
6 G
7 H
8 I
9 J
#ECHO off
setlocal ENABLEDELAYEDEXPANSION
SET allinputstring=abcdefghijk
SET lenght=10
for /l %%m in (1,1,!lenght!) do (
set /a count=0
set /a count=count+%%m
FOR %%z IN (!count!) DO echo !count! !allinputstring:~%%z,1!
)
GOTO :eof
Does this do what you require?
So... to make COUNT show (I've assigned it to KOWNT, but the syntax endlocal&set count=%count% would assign it to COUNT instead)
I've changed the starting value of the FOR/L because character counting starts from character#0 in the string.
#ECHO off
setlocal ENABLEDELAYEDEXPANSION
SET allinputstring=abcdefghij
SET lenght=9
for /l %%m in (0,1,!lenght!) do (
set /a count=0
set /a count=count+%%m
FOR %%z IN (!count!) DO echo !count! !allinputstring:~%%z,1!
)
endlocal&SET KOWNT=%count%
ECHO Now KOWNT=%KOWNT% but count=%count% because we have exited the SETLOCAL
GOTO :eof
When the ENDLOCAL is encountered, the parser substitutes the CURRENT value of the variables in the line and THEN executes the line.
Hence, the line is executed as
endlocal&set KOWNT=9
since the value of count at the time is 9.
When the SETLOCAL is executed, all changes to the environment since the matching SETLOCAL are thrown away. The environment variables are restored to their state when the SETLOCAL was executed and count becomes empty again (as it was before the routine.) THEN the SET instruction is executed, which sets KOWNT to 9.