I need to count the characters of an inputed string in Batch. I don't want to use temporary files. Could it be done without them? If yes, explanations of your code would be greatly appreciated. Thanks SO!
2 Answers
A simple way is to use a function
@echo off
set "myVar=abcdefg"
call :Stringlength result myVar
echo %result%
exit /b
:Stringlength <resultVar> <stringVar>
(
setlocal EnableDelayedExpansion
set "s=!%~2!#"
set "len=0"
for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if "!s:~%%P,1!" NEQ "" (
set /a "len+=%%P"
set "s=!s:~%%P!"
)
)
)
(
endlocal
set "%~1=%len%"
exit /b
)
This can measure the string to a maximum of 8192 characters, as the maximum size of a string is 8191 bytes, this should be enough.
The first parenthesis blocks is only for a bit more performance.
The second block is needed to return the %len%
value behind the endlocal barrier.
The main idea is a binary search, in the first loop the temporary copy in s
of the string is tested if it is longer than 4096 bytes or not.
Then the next test will be with 2048 or 6144 (=2048+4096), so the len
variable will be at each loop a little bit more exact.
After 13 loops the len is exact.
For faster strlen functions you could read strlen boosted, which uses some more tricks.
There is also a solution with batch macros, macros are normally much faster than functions in batch.
@echo off
call :loadMacros
set "myVar=abcdefg"
%$strlen% result myVar
echo %result%
exit /b
:loadMacros
set LF=^
::Above 2 blank lines are required - do not remove
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
:::: StrLen pResult pString
set $strLen=for /L %%n in (1 1 2) do if %%n==2 (%\n%
for /F "tokens=1,2 delims=, " %%1 in ("!argv!") do (%\n%
set "str=A!%%~2!"%\n%
set "len=0"%\n%
for /l %%A in (12,-1,0) do (%\n%
set /a "len|=1<<%%A"%\n%
for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"%\n%
)%\n%
for %%v in (!len!) do endlocal^&if "%%~b" neq "" (set "%%~1=%%v") else echo %%v%\n%
) %\n%
) ELSE setlocal enableDelayedExpansion ^& set argv=,
exit /b
At dostips.com are some discussion about the macro technic
1 Batch "macros" with arguments
2 macros with appended parameters

- 78,592
- 17
- 171
- 225
-
I'm sure this is faster than a basic loop but you are making assumptions about the maximum string length... – Anders May 20 '12 at 16:42
-
What is the point of the two main blocks in the function and their braces? – Anders May 20 '12 at 16:43
-
Yes I make the assumption that the string can't be longer than 8192 bytes, and that's always true, as a variable can't contain more – jeb May 20 '12 at 16:44
-
Why does the first block give better performance? The second block can probably be replaced by endlocal&set ... – Anders May 20 '12 at 16:53
-
Can someone explain the whole thing to me? I seem quite baffled by it all. I would like a top-to-down, thorough explanation. Thanks! – Ivan Spajić May 20 '12 at 18:58
-
Also, I tried making a Batch file out of it and it doesn't do anything but print pretty much everything that is written there. I need some help understanding this. Thank you! – Ivan Spajić May 20 '12 at 19:00
-
@Ivan Spajic - Then your first line should be an `@echo off` – jeb May 20 '12 at 20:10
-
@Anders - It's a caching issue, but this isn't the fastest stlen function, we made many experiments with funtions and macros to build the _best_ one, see the edited answer and links – jeb May 20 '12 at 20:10
-
+1 for the links alone, batch files sure are fun :) – Anders May 20 '12 at 21:29
When you call the function, the 2nd parameter should be a value rather than a reference:
call :Stringlength result %myVar%

- 1