Reputation: 47
I'm trying to assign a value to a variable called "doNotLog" based on the last character of some other variable called "choice" through a Batch file.
The structure of the variable choice is:
1) Either an integer with 1 or more digits
2) Or an integer with 1 or more digits plus character "n" at the last
The objectives are:
1) To set the value of "doNotLog" to true if the last character of "choice" is n
2) To finally remove n from "choice"
The Batch file I'm using to achieve this is:
@echo off
echo enter choice
set/p choice=
set doNotLog=false
setlocal ENABLEDELAYEDEXPANSION
if %choice:~-1,1%==n (
set doNotLog=true
set choice=!choice:n=!
)
endlocal
echo After changes:
echo choice= %choice%
echo donotLog= %doNotLog%
@pause
It produces the following output:
enter choice
54n
After changes:
choice= 54n
donotLog= false
Press any key to continue . . .
However, I was expecting the following output:
enter choice
54n
After changes:
choice= 54
donotLog= true
Press any key to continue . . .
How do I achieve my desired output
Upvotes: 1
Views: 5915
Reputation: 38719
Variable expansion is described under the help information for the Set
command. Open a Command Prompt window and enter set /?
to read it.
Here's some helper examples for you:
C:\Users\Mohd>Set "Variable=String"
C:\Users\Mohd>Echo(%Variable%
String
C:\Users\Mohd>Echo(%Variable:~0,-1%
Strin
C:\Users\Mohd>Echo(%Variable:~0,1%
tring
C:\Users\Mohd>Echo(%Variable:~0,-2%
Stri
C:\Users\Mohd>Echo(%Variable:~-1,1%
g
C:\Users\Mohd>Echo(%Variable:~1,-1%
trin
C:\Users\Mohd>Echo(%Variable:~1,1%
t
C:\Users\Mohd>Echo(%Variable:~1,2%
tr
C:\Users\Mohd>Echo(%Variable:~1,-2%
tri
C:\Users\Mohd>Echo(%Variable:~2,1%
r
C:\Users\Mohd>Echo(%Variable:~2,-1%
rin
C:\Users\Mohd>Echo(%Variable:~2,-2%
ri
C:\Users\Mohd>Echo(%Variable:~-2,2%
ng
C:\Users\Mohd>Echo(%Variable:~-2,1%
n
C:\Users\Mohd>Echo(%Variable:~2,-3%
r
Upvotes: 4
Reputation: 18639
The issue is that you've tried to modify doNotLog
and choice
inside a setlocal
, so you've set them locally, but the global ones remain unchanged.
Get the value of them inside setlocal
to achieve the expected result:
@echo off
echo enter choice
set/p choice=
set doNotLog=false
setlocal ENABLEDELAYEDEXPANSION
if %choice:~-1,1%==n (
set doNotLog=true
set choice=!choice:n=!
)
echo After changes:
echo choice= %choice%
echo donotLog= %doNotLog%
@pause
endlocal
If you want to disable the delayed expansion anyway, you can put the rest of the code in another setlocal
, that disables it:
@echo off
echo enter choice
set/p choice=
set doNotLog=false
setlocal ENABLEDELAYEDEXPANSION
if %choice:~-1,1%==n (
set doNotLog=true
set choice=!choice:n=!
)
setlocal DISABLEDELAYEDEXPANSION
echo After changes:
echo choice= %choice%
echo donotLog= %doNotLog%
@pause
:: We have to end two locals now...
endlocal
endlocal
...however, if you do this multiple times, your code will quickly become unmaintainable (oh, wait, aren't all batch files unmaintainable?) and less performant.
Alternatively, you can move variables out of local by using the magic of single-line or parenthesis-grouped commands, and the classic %variable%
syntax:
endlocal & set "doNotLog=%doNotLog%" & set "choice=%choice%"
...or the equivalent, but more readable...
(
endlocal
set "doNotLog=%doNotLog%"
set "choice=%choice%"
)
The above solutions might look silly, but they do work...
Both of the above will set global variables, because they're after endlocal
, but read the local ones, as they're substituted before the evaluation of the line (or the grouped structure) starts. (That's why these hacks work with the %var%
syntax, but not with the !var!
)
So, your code can even be changed to:
@echo off
echo enter choice
set/p choice=
set doNotLog=false
setlocal ENABLEDELAYEDEXPANSION
if %choice:~-1,1%==n (
set doNotLog=true
set choice=!choice:n=!
)
endlocal & (
set "doNotLog=%doNotLog%"
set "choice=%choice%"
)
echo After changes:
echo choice= %choice%
echo donotLog= %doNotLog%
@pause
...which may be the best solution among these.
Upvotes: 1
Reputation: 2565
So, what about without using SetLocal EnableDelayedExpansion
@echo off
set "doNotLog=" && set "choice="
for /f ^skip^=^4 %%a in ('echo/ prompt $h^| cmd
')do echo/ && set/p "choice=-%%a Enter choice: "
echo/%choice:~-1%|find /i "n">nul && (
call set "choice=%choice:~0,-1%" && set "doNotLog=true")
if "%doNotLog%" == "" set "doNotLog=false"
echo/ choice = %choice% && echo/ doNotLog = %doNotLog%
echo/ Press any key to continue... & timeout -1 >nulF
54n
and 54
::
G:\SO_en-EN\Q59738810>Q59738810.cmd
Enter choice: 54n
choice = 54
doNotLog = true
Press any key to continue...
---------------------------------------
G:\SO_en-EN\Q59738810>Q59738810.cmd
Enter choice: 54
choice = 54
doNotLog = false
Press any key to continue...
Upvotes: 0