mzn
mzn

Reputation: 47

Removing last character from a variable in a Batch file

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

Answers (3)

Compo
Compo

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

FZs
FZs

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

Io-oI
Io-oI

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

  • outputs for input 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

Related Questions