Reputation: 49
I have two batch file here, test.bat
and len.bat
.
len.bat
is a function that receives input from test.bat
, processes it and then return a result value back to test.bat
.
test.bat
@echo off
setlocal EnableDelayedExpansion
call len tesla
echo !result!
pause
len.bat
@echo off
setlocal EnableDelayedExpansion
set "string=%~1"
for /l %%a in (0,1,10000) do if "!string:~%%a,1!" == "" (
set result=%%a
exit /b
)
When I open test.bat
, I expect it would print a value. Instead, it says Echo is OFF.
There seem to be a problem passing the variable from len.bat
to test.bat
.
Upvotes: 1
Views: 121
Reputation: 14304
setlocal
can be thought of as a sandbox, and anything created inside of that sandbox exists for as long as the sandbox exists. The sandbox stops existing when endlocal
is called - either explicitly, or implicitly when the script ends.
In len.bat
, you add a sandbox inside of the sandbox with a second setlocal enabledelayedexpansion
command, and !result!
is created inside of that inner sandbox. When len.bat
ends, !result!
is destroyed since it didn't exist before len.bat
was called.
I suspect that you added the second setlocal enabledelayedexpansion
because you thought it was needed to use delayed expansion inside of len.bat
, but delayed expansion is actually still enabled because it was turned on in test.bat
.
Delete the setlocal enabledelayedexpansion
from len.bat
and test.bat
will correctly return "5".
If you feel that you need to keep the setlocal enabledelayedexpansion
in len.bat
to use it separately from test.bat
, you can explicitly call endlocal
and chain the set
command to it to trick the interpreter into letting the variable escape the sandbox.
@echo off
setlocal EnableDelayedExpansion
set "string=%~1"
for /l %%a in (0,1,10000) do if "!string:~%%a,1!" == "" (
endlocal & set result=%%a
exit /b
)
Upvotes: 3
Reputation: 38579
Does this help you out? The string length is returned as %ErrorLevel%
:
New len.bat
@Set "str=#%~1" & SetLocal EnableDelayedExpansion
@Set "len=0" & For /L %%G In (12,-1,0) Do @(Set /A "len |= 1 << %%G"
For %%H In (!len!) Do @If "!str:~%%H,1!" == "" Set /A "len &= ~ 1 << %%G")
@EndLocal & Exit /B %len%
Example test.bat
@Call "len.bat" four
@Echo %ErrorLevel% & Pause
@Call "len.bat" "nineteen inc spaces"
@Echo %ErrorLevel% & Pause
Upvotes: 2