Good catch WernerGg - you have discovered a limitation/bug in the existing :toLower code and come up with a working fix.
Given that your modified code is already using SETLOCAL ENABLEDELAYEDEXPANSION, the following two lines:
Code: Select all
set str=%~1
call set "str=%%%str%%%"
can be replaced by the much simpler:
Also your final assignment in the ENDLOCAL block should be enclosed in quotes in case of special characters:
There still can be problems if the string contains both quotes and special characters, but the enclosing quotes are a wothwhile improvement.
The original :toLower fails with any variable starting with lower case <a> because the leading <a> is interpreted as the %%a of the for loop. You can see what I mean by setting ECHO ON before the for loop.
The same problem exists for the existing :toUpper and :toCamelCase functions. I think all three functions should be updated with variants of your fix.
WernerGg wrote:BTW: This toLower algorithm is very expensive. Basically there is a double loop. An outer loop over all 29 alphabetic characters. For each of this 29 steps we get one inner loop over all characters of the hole string during !str:%%~a!. And then an assignement during set str=!str:%%~a!. Most of that efforts change nothing but are necessary.
Nobody would program like that in a standard programming language. One would have just one loop over the characters of the string and use the ascci-value of each character as an index into a 256-sized toLower-translation array.
Ahh, but DOS is not a normal programming language! If you compare how long it takes to process a short string vs. a long string, there is barely a difference. That is because the loop iteration count is fixed at 29 and the string substitution uses compiled, optimized code that is comparatively much faster than the interpreted batch language it is embedded within. Switching to an iteration over the characters within the string will actually slow the function down, especially as the string grows, even though logically it should be more efficient. The situation is made worse because there are no built in functions to determine the length of a string or the ascii value of a character.
Dave Benham