Discussion forum for all Windows batch related topics.
Moderator: DosItHelp
-
billrich
- Posts: 70
- Joined: 24 Apr 2012 05:36
- Location: USA
#16
Post
by billrich » 23 Sep 2012 14:25
dbenham wrote:
The DosTips strlen function handles all possible strings up to the max length supported by batch (actually maxLength-1), and completes in the blink of an eye.
Dave Benham
I can find no examples of members using the DosTips strlen function other than the example where the user furnishes the strings one at time.
The following code gets the strings from dir /b a*.bat. May we see the correct way to gather the strings for the Dostips strlen function?
Thanks for your help.
Code: Select all
@echo off
setlocal enabledelayedexpansion
for /f "delims=" %%i in ('dir /b a*.bat') do (
set "string="
set string=%%i
echo string=!string!
CALL :StrLen string Len
ECHO Length = !Len!
)
EXIT /b
:strLen string len -- returns the length of a string
:: -- string [in] - variable name containing the string being measured for length
:: -- len [out] - variable to be used to return the string length
:: Many thanks to 'sowgtsoi', but also 'jeb' and 'amel27' dostips forum users helped making this short and efficient
:$created 20081122 :$changed 20101116 :$categories StringOperation
:$source http://www.dostips.com
( SETLOCAL ENABLEDELAYEDEXPANSION
set "str=A!%~1!"&rem keep the A up front to ensure we get the length and not the upper bound
rem it also avoids trouble in case of empty string
set "len=0"
for /L %%A in (12,-1,0) do (
set /a "len|=1<<%%A"
for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"
)
)
( ENDLOCAL & REM RETURN VALUES
IF "%~2" NEQ "" SET /a %~2=%len%
)
EXIT /b
Output:
C:\test>tipsstr.bat
string=A.bat
Length = 5
string=AA.bat
Length = 6
string=aaron.bat
Length = 9
string=ab.bat
Length = 6
string=abc.bat
Length = 7
string=abcd.bat
Length = 8
string=Abhi.bat
Length = 8
string=abhi2.bat
Length = 9
string=Abnew.bat
Length = 9
string=acall.bat
Length = 9
string=add.bat
Length = 7
string=add2.bat
Length = 8
string=adh.bat
Length = 7
string=adhold.bat
Length = 10
string=agedel.bat
Length = 10
string=ana.bat
Length = 7
string=andrea.bat
Length = 10
string=anup.bat
Length = 8
string=arc.bat
Length = 7
string=arguments.bat
Length = 13
C:\test>
-
billrich
- Posts: 70
- Joined: 24 Apr 2012 05:36
- Location: USA
#17
Post
by billrich » 27 Sep 2012 17:42
Code: Select all
@echo off
rem jimlen.bat hello world
echo Usage: jimlen.bat hello world
setlocal enabledelayedexpansion
set string=%*
:loop
set /A cnt+=1
if not "!string:~%cnt%,1!"=="" goto loop
echo.string length = %cnt%
rem code posted by T.C. at computerhope.com
Output:
C:\test>jimlen.bat hello world
Usage: jimlen.bat hello world
string length = 11
C:\test>jimlen.bat 77777
Usage: jimlen.bat hello world
string length = 5
C:\test>jimlen.bat hello world
string length = 11
C:\test>jimlen.bat hello
string length = 5
C:\test>jimlen.bat 77777
string length = 5
C:\test>jimlen.bat <αßc??>,
string length = 8
C:\test>
p.s Some of the DosTips experts do not know how to run a program that requires arguments:
jimlen.bat hello world
Last edited by
billrich on 02 Oct 2012 04:32, edited 3 times in total.
-
Squashman
- Expert
- Posts: 4486
- Joined: 23 Dec 2011 13:59
#18
Post
by Squashman » 27 Sep 2012 18:12
billrich wrote:Code: Select all
@echo off
setlocal enabledelayedexpansion
set string=%*
:loop
set /A cnt+=1
if not "!string:~%cnt%,1!"=="" goto loop
echo.string length = %cnt%
Try that with this string: !&%$^*()!
-
Squashman
- Expert
- Posts: 4486
- Joined: 23 Dec 2011 13:59
#19
Post
by Squashman » 27 Sep 2012 18:59
Thought I would show this code for getting length. Was one posted buy a user on another forum a while back but of course it has issues with some of the poison characters. It is interesting what it does when you use all carets.
Mostly just posting this because of the concept it uses to get the length. Definitely not fool proof.
Code: Select all
@echo off
SetLocal
Set _Len=0
Set "_Str=%*"
If NOT Defined _Str Goto :EOF
Set _Str=%_Str:"=.%987654321
:_Loop
If NOT "%_Str:~18%"=="" Set _Str=%_Str:~9%& Set /A _Len+=9& Goto _Loop
Set _Num=%_Str:~9,1%
Set /A _Len=_Len+_Num
echo %_Len%
endlocal
Code: Select all
C:\Users\Squashman\Batch>outlen.bat !123456789123456789!
20
C:\Users\Squashman\Batch>outlen.bat %123456789123456789%
20
C:\Users\Squashman\Batch>outlen.bat %123456789123456789%&&
The syntax of the command is incorrect.
C:\Users\Squashman\Batch>outlen.bat %123456789123456789% 1
22
C:\Users\Squashman\Batch>outlen.bat %12345678^9123456789%
20
C:\Users\Squashman\Batch>outlen.bat %12345678^^9123456789%
20
C:\Users\Squashman\Batch>outlen.bat %12345678^^9123456789%^^
20
C:\Users\Squashman\Batch>outlen.bat ^^^^^^^^^^^^^^^
More?
More?
3
C:\Users\Squashman\Batch>
-
Liviu
- Expert
- Posts: 470
- Joined: 13 Jan 2012 21:24
#20
Post
by Liviu » 27 Sep 2012 19:01
Squashman wrote:Try that with this string: !&%$^*()!
You are making it way too complicated
Just run bill's code with no arguments at all, and prepare to be very very patient. Or, for a challenge, explain why the length of ^^ returns as 5. But I think we all know it's a waste of time.
-
Liviu
- Expert
- Posts: 470
- Joined: 13 Jan 2012 21:24
#21
Post
by Liviu » 27 Sep 2012 19:10
Squashman wrote:Mostly just posting this because of the concept it uses to get the length.
Didn't follow it in full detail, but looks like it reduces the loops by a (linear) factor of 9. That's a clever trick, indeed, but dostips' :strlen easily beats it with the (exponential) log2 reduction.
-
dbenham
- Expert
- Posts: 2461
- Joined: 12 Feb 2011 21:02
- Location: United States (east coast)
#22
Post
by dbenham » 27 Sep 2012 20:11
I haven't done any rigorous timing, but I think this is about as fast as the DosTips StrLen function, though it uses a temporary file.
I think I first saw this basic technique in a StackOverflow post by Aacini. I don't know how long the idea has been around.
Code: Select all
@echo off
:strLen strVar [rtnVar]
setlocal enableDelayedExpansion
set "tempFile=%temp%\strLen%random%.txt"
>"%tempFile%" echo(!%~1!
for %%F in ("%tempFile%") do set /a "rtn=%%~zF - 2"
del "%tempFile%"
(endlocal
if "%~2" neq "" (set "%~2=%rtn%") else echo %rtn%
)
exit /b
Dave Benham
-
Liviu
- Expert
- Posts: 470
- Joined: 13 Jan 2012 21:24
#23
Post
by Liviu » 27 Sep 2012 21:46
dbenham wrote:I haven't done any rigorous timing, but I think this is about as fast as the DosTips StrLen function, though it uses a temporary file.
Maybe not literally "as fast" but close, yes. Not claiming full rigor, but running both on strings of increasing lengths, the dostips :strlen comes 10%-15% faster on my test machine. Pedantic footnote, it stops counting at length 8,185 while the code you quoted goes one byte farther i.e. gets 8,185 right but fails on 8,186.
Liviu