I'm attempting to rewrite an .sh script to a .bat file so that I can test it on Windows VM.
I have encountered an issue with FOR /F loop, I am unable to use the variables I set in the loop, I'm really frustrated about this. I have been looking around for a while and I have enabled delayed expansion, to no luck. Below is the piece of code :
setlocal ENABLEDELAYEDEXPANSION
FOR /F "eol=; tokens=1,2,3,4,5,6,7,8,9,10 delims=, " %%i in (%SOutPath%) do (
SET sKic1Length = 20
SET sRAMTar = %%i
SET admCode = %%j
SET pin1Code = %%k
SET pin2Code = %%l
SET sKic1 = %%m
SET sKic1Length = %%n
SET sKid1 = %%o
SET sKid1Length = %%p
SET sRAMMSL=%%r
IF sKic1Length EQU 16 SET sKic1Length=11
IF sKic1Length EQU 32 SET sKic1Length=15
IF sKic1Length EQU 48 SET sKic1Length=19
::This echo outputs 'Echo is off' so variable is empty
#echo %sKic1Length%
)
::Also returns same
ECHO %sKid1Length%
Below is the file that I'm reading in the loop :
; ;, RAMTAR, ADM1, PIN1, PIN2, KIC1, KICLENGTH,KID1, KIDLENGTH, RAMMSL
000000, 17182320, 2387, 1116, 607038CA34A91FB1, 16, 607038CA34A91FB, 16, 0200
I would appreciate any input.
Thank you
You have to use ! instead of % on ENABLEDELAYEDEXPANSION in a loop
#echo off
setlocal ENABLEDELAYEDEXPANSION
for /f "eol=; tokens=1,2,3,4,5,6,7,8,9,10 delims=, " %%i in (%SOutPath%) do (
set "sKic1Length=20"
set "sRAMTar=%%i"
set "admCode=%%j"
set "pin1Code=%%k"
set "pin2Code=%%l"
set "sKic1=%%m"
set "sKic1Length=%%n"
set "sKid1=%%o"
set "sKid1Length=%%p"
set "sRAMMSL=%%r"
if "!sKic1Length!" equ "16" set "sKic1Length=11"
if "!sKic1Length!" equ "32" set "sKic1Length=15"
if "!sKic1Length!" equ "48" set "sKic1Length=19"
echo.!sKic1Length!
)
echo.%sKid1Length%
endlocal
If the last echo returns nothing, then I assume, that in the last iteration %%p was empty.
Related
I want to use a variable skip parameter in for loop, but it won't let me do it.
Here is my code
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /p testcase=<testcases.txt
set /a end=%testcase%*13
for /L %%P IN (1,13,%end%) DO (
set skip=skip=%%P
echo !skip!
set vidx=0
for /f "%skip%" %%A in (testcases.txt) do (
set /a vidx=!vidx! + 1
set var!vidx!=%%A
)
)
Here skip is skip=1, but it doesn't skip any line. When I replace it with skip=1. then it works fine, but I want to skip variable no. of lines in each iteration. Please help.
I think with this logic the only option is a subroutine:
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /p testcase=<testcases.txt
set /a end=%testcase%*13
for /L %%P IN (1,13,%end%) DO (
set skip=skip=%%P
echo !skip!
set vidx=0
call :innerFor %%P
)
exit /b 0
:innerFor
for /f "skip=%~1" %%A in (testcases.txt) do (
set /a vidx=!vidx! + 1
set var!vidx!=%%A
)
exit /b 0
parametrization of FOR /F options is a little bit tricky..
Though I have no the content of your files I cant test if this works correctly .
I want to do this:
set kommune
FOR /F "tokens=* delims=" %%x in (DBLib.txt) DO (
CALL :decryptLine "%%x"
)
GOTO:eof
:decryptLine
for /f "tokens=1,* delims==" %%a in ("%~1") do set argument=%%a & set value=%%b
set "argument=%argument:~0,-2%"
set "value=%value:~1%"
call:updateVar "%argument%" "%value%"
GOTO:EOF
:updateVar
IF "%~1" == "KommuneNavn" (
ECHO "%~2"
ECHO "KommuneNavn"
set kommune=%~2
ECHO kommune = "%kommune%" testhest
)
What it outputs:
"ABC Test Kommune"
"KommuneNavn"
"kommune = "" testhest"
How do i copy the value of the secont argument to the Variable "kommune"? And Echo it?
Edit 1: updated to exact code. "inside IF"
#ECHO OFF
SETLOCAL
set kommune
FOR /F "tokens=* delims=" %%x in (q27922463.txt) DO (
CALL :decryptLine "%%x"
)
GOTO:eof
:decryptLine
for /f "tokens=1,* delims==" %%a in ("%~1") do set "argument=%%a" & set "value=%%b"
set "argument=%argument:~0,-2%"
set "value=%value:~1%"
call:updateVar "%argument%" "%value%"
GOTO:EOF
:updateVar
IF "%~1" == "KommuneNavn" (
ECHO "%~2"
ECHO "KommuneNavn"
set kommune=%~2
CALL ECHO kommune = "%%kommune%%" testhest
)
GOTO :eof
Critical point: You haven't shown us the content of your file, so we have to construct it: and I've changed the filename to suit my system (q27922463.txt)
contents of q27922463.txt
KommuneNavnxy=yourvalue
output generated:
"ourvalue"
"KommuneNavn"
kommune = "ourvalue" testhest
Note the positioning of the quotes in the set assignments. Batch is sensitive to spaces in a SET statement. SET FLAG = N sets a variable named "FLAGSpace" to a value of "SpaceN"
So, %%a becomes KommuneNavnxy, is assigned to argument, and the last 2 characters are removed, making KommuneNavn
Similarly, %%b gets yourvalue, you remove the first and make ourvalue
Since the string kommune is set within the code block of the if statement, you need to use call echo %%var%% to display it (one of several ways).
I have to make a script that has to calculate the mask and the net, so I'm trying a script with for but it can not convert the IP to binary. I think I'm not using the variables right.
Any ideas?
#echo off
setlocal enabledelayedexpansion
set var=%1
set /p var=Introduce la ip:
for /F "tokens=1 delims=." %%a in ("%var%") do (
echo %%a
set "vara=%%a"
:binario
set bin=2
set /a resto=%vara%%%bin%
set /a a=%vara%/%bin%
set resultado=%resto%%resultado%
if %vara% GTR 0 (goto binario)
echo %resultado%
goto siguiente
)
:siguiente
for /F "tokens=2 delims=." %%b in ("%var%") do (
echo %%b
)
for /F "tokens=3 delims=." %%c in ("%var%") do (
echo %%c
)
for /F "tokens=4 delims=." %%d in ("%var%") do (
echo %%d
)
goto fin
:vacio
echo Error!
goto fin
:fin
pause
You've got a few minor problems that I see. You set var=%1 but you never check to see whether %1 was supplied before doing set /p var=Enter an IP:. You never call or goto :vacio. As I commented above, modulos within batch scripts need to be written as %% to prevent evaluation as variable chararacters. You don't need % in var names in set /a commands, and you can combine multiple set /a statements with a comma. So instead of
set /a resto=%vara%%%bin%
set /a a=%vara%/%bin%
(which is wrong anyway -- I'll get to that in a minute), I suggest this would be more understandable and maintainable:
set /a resto = vara %% bin, numero = vara / bin
The biggest problem is that you appear to be trying to modify %%a. Don't do that.
If I were you, I would move the decimal to binary conversion to a subroutine, and call it for each octet. Try this:
#echo off
setlocal enabledelayedexpansion
set IP=%1
if "%IP%"=="" set /p "IP=Introduce la ip: "
set idx=0
for %%a in (%IP:.= %) do (
if %%a lss 0 goto vacio
if %%a gtr 255 goto vacio
if !idx! gtr 3 goto vacio
set /P "=%%a = "<NUL
call :dec2bin bin[!idx!] %%a
set /a idx += 1
)
echo %bin[0]%.%bin[1]%.%bin[2]%.%bin[3]%
goto fin
:dec2bin <var_para_definir> <numero>
setlocal enabledelayedexpansion
set numero=%~2
set bin=
for /L %%I in (1,1,8) do (
set /a bit = numero %% 2, numero /= 2
set bin=!bit!!bin!
)
echo %bin%
endlocal & set "%~1=%bin%"
goto :EOF
:vacio
echo Error!
goto fin
:fin
pause
For more information about using call as a function that returns a value, see this page.
in Windows Batch, if I had a variable (length can change) that was, for example: "hello world!"
is it possible to "split" the variable so each character is its own variable so the output could look like:
t1=h
t2=e
t3=l
etc.
Any help would be appreciated.
Use this code:
setlocal EnableDelayedExpansion
set str="hello world^!"
set tempstr=%str%
set count=0
:loop
if defined tempstr (
set tempstr=%tempstr:~1%
set /a count+=1
set /a pos=%count%-1
set t!count!=!str:~%pos%,1!
goto loop
)
:: check the generated variables
set t
To get the nth character in a string, use set char=%str:~n,1%.
I hope this was helpful!
Here is a variant using for /L to iterate over all characters of the string. The number of characters, so the length of the string, is retrieved in sub-routine :LENGTH first:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_STRING=Hello world!"
call :LENGTH LEN "%_STRING%"
setlocal EnableDelayedExpansion
for /L %%I in (0,1,%LEN%) do (
set "$CHR[%%I]=!_STRING:~%%I,1!"
)
set $CHR
endlocal
endlocal
exit /B
:LENGTH rtn_length val_string
setlocal DisableDelayedExpansion
set /A "RET=0" & set "STR=%~2"
if defined STR set /A "RET=1"
setlocal EnableDelayedExpansion
for %%L in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if not "!STR:~%%L,1!"=="" (
set /A "RET+=%%L"
set "STR=!STR:~%%L!"
)
)
(
endlocal
endlocal
set "%~1=%RET%"
)
exit /B
Here is a different variant, using cmd /U to convert the string into Unicode, where a null-byte becomers inserted behind every character, and find, which treats these null-bytes like end-of-line markers:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_STRING=Hello world!"
set /A "IDX=0"
for /F delims^=^ eol^= %%I in ('
cmd /U /V /C echo^(!_STRING!^| find /V ""
') do (
set "CHR=%%I"
setlocal EnableDelayedExpansion
for /F "delims=" %%J in ("$CHR[!IDX!]=!CHR!") do (
endlocal
set "%%J"
)
set /A "IDX+=1"
)
set $CHR
endlocal
exit /B
Finally, here is another variant, based on a goto loop. This uses a position pointer POS to scan the string and to extract a single character. If no character is returned, the end of the string is reached:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_STRING=Hello world!"
setlocal EnableDelayedExpansion
if not defined _STRING goto :QUIT
set /A "POS=0"
:LOOP
set "CHR=!_STRING:~%POS%,1!"
if defined CHR (
set "$CHR[%POS%]=!CHR!"
set /A "POS+=1"
goto :LOOP
)
:QUIT
set $CHR
endlocal
endlocal
exit /B
Old thread, but accepted answer misses letter d?
Changed
set /a pos=%count%-1 to
set /a pos=!count!-1
setlocal EnableDelayedExpansion
set str="hello world!"
set tempstr=%str%
set count=0
:loop
if defined tempstr (
set tempstr=%tempstr:~1%
set /a count+=1
set /a pos=!count!-1
set t!count!=!str:~%pos%,1!
goto loop
)
:: check the generated variables
set t
pause
Here is another version.
variables start with 0, though
setlocal EnableDelayedExpansion
set var="hello world!"
rem remove quotes
set var=%var:"=%
rem add limiter
set var=%var%_
echo %var%
set count=0
:loop
set tempvar=!var:~%count%,1!
if !tempvar!==_ goto skip
set arr!count!=!tempvar!
set /a count=!count!+1
goto loop
:skip
echo out
echo display output
set arr
pause
I have this code to read a text file.
#ECHO OFF
SetLocal EnableDelayedExpansion
for /f "delims=" %%x in ('type text.txt') do (
set "Var=%%x"
ECHO !Var!
)
pause
My question is that if i could advance every char in the file by 20 places like "a" would be "t". it can have numbers and symbols too. the txt file is 400 line long and there is between 1 and 120 char per line. does any one know how i could do this.
Sorry, this will not handle all the posibilities, but
#echo off
setlocal enableextensions disabledelayedexpansion
call :setTables
set "inputFile=inputFile.txt"
for /f "usebackq delims=*" %%a in ("%inputFile%") do (
set "data=%%a"
call :handleProblems
set "out="
setlocal enabledelayedexpansion
for /f "delims=" %%b in ('cmd /v:off /q /u /c "echo(!data!"^|more') do (
if defined "%%b" (
set "out=!out!!"%%b"!"
) else (
set "out=!out!%%b"
)
)
echo(!out!
endlocal
)
exit /b
:handleProblems
set "data=%data:!=~%"
set "data=%data:<=^<%"
set "data=%data:>=^>%"
set "data=%data:&=^&%"
set "data=%data:|=^|%"
set "data=%data:)=^)%"
exit /b
:setTables
set ""a"=t"
set ""b"=u"
set ""c"=v"
set ""d"=w"
set ""e"=x"
set ""f"=y"
set ""g"=z"
set ""h"=a"
set ""i"=b"
set ""j"=c"
set ""k"=d"
set ""l"=e"
set ""m"=f"
set ""n"=g"
set ""o"=h"
set ""p"=i"
set ""q"=j"
set ""r"=k"
set ""s"=l"
set ""t"=m"
set ""u"=n"
set ""v"=o"
set ""w"=p"
set ""x"=q"
set ""y"=r"
set ""z"=s"
set ""~"=!"
set ""^&"=&"
exit /b
Use GnuSed and the "y/abc/tuv/" transliteration command which would replace a with t, b with u and c with v
This syntax works - just extend the character sets:
sed "y/abc/tuv/" "file.txt" >"newfile.txt"