I have this code:
setlocal enableDelayedExpansion
set count=0
set letter=a,b,c
for %%a in (%letter%) do (
set /a "count+=1"
echo %count%
)
pause
The output is:
0
0
0
I want that the output will be:
1
2
3
I also tried to do it without EnableDelayedExpansion, but I had no luck. What did I do wrong?
you need to
echo !count!
with delayedexpansion
or
call echo %%count%%
%count% will always return the value of count as it stood when the block (parenthesised series of statements) was encountered.
Related
Im trying to make a batch file that loops thru an array containing numbers like this: 1 2 3 4 5.
In the first itteration of the loop I like to pick token 1 and 2. In the second 2 and 3, in the third 3 and 4 and so on.
I do think I should use ! in the variables first and second that I use as tokens. Like in the first FOR /F, but when I do, I get: !first!" was not expected here.
And if I use %, it does not count up.
Everything works except the variable tokens. Any one knowes how to? Any help or suggestions greatly appriciated.
This is the part Im struggeling with:
setlocal EnableDelayedExpansion
set first=1
set second=2
set N=4
set output="1 2 3 4 5"
set output=%output:"=%
for /L %%a in (1,1,%N%) do (
if !counter! equ active (
set /a first+=1
set /a second+=1
)
FOR /F "tokens=!first!" %%a IN ("%output%") DO (
set nr1=%%a
)
FOR /F "tokens=%second%" %%a IN ("%output%") DO (
set nr2=%%a
)
echo nr1 var: !nr1!
echo nr2 var: !nr2!
echo counter f: !first!
echo counter s: !second!
set counter=active
)
You cannot use delayed expanded variables in the options string of for /F. Neither can you use other for variables for that. But you can use normally (immediately) expanded variables. Also you can use argument references like %1, for example.
So a nice work-around for your problem is to place the for /F loop in a sub-routine and use call in the main program with the delayed expanded variables as arguments, like this:
#echo off
setlocal EnableDelayedExpansion
set /A first=1
set /A second=2
set /A N=4
set "output=1 2 3 4 5"
set "counter="
for /L %%a in (1,1,%N%) do (
if defined counter (
set /A first+=1
set /A second+=1
)
call :SUB !first! !second!
echo nr1 var: !nr1!
echo nr2 var: !nr2!
echo counter f: !first!
echo counter s: !second!
set "counter=active"
)
endlocal
exit /B
:SUB val_token1 val_token2
for /F "tokens=%~1,%~2" %%a in ("%output%") do (
if %~1 LSS %~2 (
set "nr1=%%a"
set "nr2=%%b"
) else if %~1 GTR %~2 (
set "nr1=%%b"
set "nr2=%%a"
) else (
set "nr1=%%a"
set "nr2=%%a"
)
)
exit /B
Since you are extracting tokens from the same string, I combined your two for /F loops into a single one. The if block in the for /F loop in the sub-routine :SUB is there just in case the second token number is not always greater than the first one. But if that can guaranteed, the for /F loop needs to contain only set "nr1=%%a" and set "nr2=%%b".
I'm trying to do something like this, but I can't make it to work.
for /F "tokens=1" %%a in (C:\Auxiliar4.txt) do (
if !counter! EQU 3 (set /A failed=%%a)
if !counter! EQU 9 (set /A completed=%%a)
if !counter! EQU 6 (set /A total=%%a)
set /A counter+=1
)
set /A counter=0
set /A failedday=%failedday%+%failed%
if %total% NEQ 0 (set /A success=(%completed%*100)/%total%)
My problem is with these two lines:
set /A failedday=%failedday%+%failed%
if %total% NEQ 0 (set /A success=(%completed%*100)/%total%)
The first issue is with variable "failedday", I need to read numeric values from a txt file, assign them to those variables (failed, completed, total) and then assign the value of "failed" to "failedday". Then another FOR loop starts to read a different txt with same format, assign those numeric values to "failed", "completed", "total" again (losing the previous values), and add new value of "failed" to "failedday" keeping the previous addition (example, filedday=2 after first "for", after second should be failedday=2 + New"Failed"Value).
The second issue is with "IF" structure. I need to calculate the average of completed transactions taking values from "For" loop, only if "total" is not equal to 0 (to avoid divide by zero), but when I add this line my script crashes.
Could anyone help me with this? Thanks!!!
Here's a previous StackOverflow question that asks the same sort of thing.
Here's another reference for doing arithmetic with DOS Batch files.
You need to enable delayed expansion to perform the arithmetic:
#echo off & setlocal EnableDelayedExpansion
set /A failed=0
set /A completed=0
set /A total=0
for /F "tokens=1" %%a in (C:\Temp\test.txt) do (
if !counter! EQU 3 (set /A failed=%%a)
if !counter! EQU 9 (set /A completed=%%a)
if !counter! EQU 6 (set /A total=%%a)
set /A counter+=1
)
echo Failed: %failed%
echo Completed: %completed%
echo Total: %total%
set /A counter=0
set /A failedday=failedday+failed
if total NEQ 0 (set /A success=completed*100/total)
echo Success: %success%
I am trying to make a batch file to solve the first Project Euler problem, http://projecteuler.net/problem=1, but I need an if statement inside my loop to check if n modulo 3 or 5 is 0. And the sum has suddenly stopped working.
My code:
echo off
set sum=0
for /l %%n in (1,1,999) do (
set a/ sum+=%%n *(only add if n%%3 == 0 or n%%5 == 0)*
)
echo %sum%
pause
Here is a very efficient solution, though it is a bit obfuscated:
#echo off
setlocal
set /a sum=0
for /l %%N in (1 1 999) do set /a "sum+=%%N/!((%%N%%5)*(%%N%%3))" 2>nul
echo %sum%
The expression (%%N%%5)*(%%N%%3) yields zero if %%N is divisible by 3 or 5, or non-zero if it is not divisible by either. The ! takes the inverse logical value, so 0 becomes 1, and non-zero becomes 0. Dividing %%N by that expression yields either %%N or a division by zero error. So simply add that entire expression to the sum, and redirect error messages to nul.
Final result - only numbers divisible by 3 or 5 are added :-)
#ECHO OFF
SETLOCAL
set /A sum=0
for /l %%n in (1,1,999) do (
CALL :modulo %%n
IF DEFINED addme set /a sum+=%%n
REM CALL echo %%n %%sum%% %%addme%%
)
echo %sum%
GOTO :EOF
:modulo
:: set addme if %1 %% 3 == 0 or %1 %% 5 == 0
SET /a addme = %1 %% 3
IF %addme%==0 GOTO :EOF
SET /a addme = %1 %% 5
IF %addme%==0 GOTO :EOF
SET "addme="
GOTO :eof
Simply pass each value to the :modulo routine in turn and set a flag value to (clear or not)
OR
#ECHO OFF
SETLOCAL enabledelayedexpansion
set /A sum=0
for /l %%n in (1,1,999) do (
SET /a mod=%%n %% 3
IF NOT !mod!==0 SET /a mod=%%n %% 5
IF !mod!== 0 set /a sum+=%%n
rem CALL echo %%n %%sum%%
)
echo %sum%
GOTO :EOF
which does the same thing using delayedexpansion.
And the sum has suddenly stopped working.
I think your sum stopped working because your set needs to have the slash in front of the 'a', and not behind it, like this:
SET /A sum+=%%n
Also, there isn't an OR operator in DOS Batch, so you'll need to use a nested IF for that. This worked for me:
echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set sum=0
for /l %%n in (1,1,999) do (
SET /A mod3=%%n%%3
SET /A mod5=%%n%%5
IF !mod3!==0 (
SET /A sum+=%%n
) ELSE (
IF !mod5!==0 (
SET /A sum+=%%n
)
)
)
echo %sum%
ENDLOCAL
If you need more help, check out Rob van der Woude's Scripting pages. Specifically, here is a link to his page on performing mathematical operations in DOS batch files.
I have created a simple program to print numbers 1 to 10 and store them in a text file:
#echo off
SET /A X=1
:START
IF %X% LEQ 10 (
ECHO %X%>>C:\TXT.TXT
SET /A X+=1
GOTO START
)
PAUSE
Output that I am getting is:
ECHO OFF
10
Where have I gone wrong?
You could use a for loop for this (not an if statement):
FOR /L %i IN (1,1,10) do echo %i
(this loops from 1 to 10 in command line)
See also: http://ss64.com/nt/for_l.html
EDIT (as I tried to put the code in my comment -> if you change your code to output in the console, you'll see that your code does work, but in your case the txt only has the last time your echo'd):
#echo off
SET /A X=1
:START
IF %X% LEQ 10 (
ECHO %X%
SET /A X+=1
GOTO START
)
pause
I have a small block of code that is supposed to parse through a file called data.dta but for some reason it keeps saying ( unexpected at this time, here is the code(I put a comment by the line that gives me an error):
:load
cd %appdata%\.Trek
FOR /f "eol=#" %%t IN (Resources\Data\data.dta) DO ( ::problem line
set count=1
set cor=0
FOR /f "tokens=1-2 delims=^=" %%f IN ("%%t") DO (
If %count% == 1 (
IF %%f==VERSION set cor=1
)
If %count% == 2 (
IF %cor%==1 (
set cor=0
set ver=%%f
)
)
set /a count=%count%+1
)
)
Title TREK Unmounted Console Version: %ver%
Contents of data.dta:
VERSION=ALPHA 2
I can spot one major problem, you need to enable delayed expansion for it to work.
In a code block, all variables will have the value of what they were set before the code block started. If you set a variable inside a code block, it will only have that value once it is outside of the code block.
Try this example:
#echo off
set var=1
echo %var%
for /l %%i in (1,1,5) do (
set /a var+=1
echo %var%
)
echo %var%
pause>nul
The output will be:
1
1
1
1
1
1
6
Now, try it with delayed expansions enabled, and replace the percent signs with exclamation marks:
#echo off
setlocal enabledelayedexpansion
set var=1
echo %var%
for /l %%i in (1,1,5) do (
set /a var+=1
echo !var!
)
echo %var%
Output:
1
2
3
4
5
6
6
So, change your code to:
:load
cd %appdata%\.Trek
setlocal enabledelayedexpansion
FOR /f "eol=#" %%t IN (Resources\Data\data.dta) DO (
set count=1
set cor=0
FOR /f "tokens=1-2 delims=^=" %%f IN ("%%t") DO (
If !count! == 1 (
IF %%f==VERSION set cor=1
)
If !count! == 2 (
IF !cor!==1 (
set cor=0
set ver=%%f
)
)
set /a count+=1
)
)
Title TREK Unmounted Console Version: %ver%
endlocal
...And see what happens now.