为了账号安全,请及时绑定邮箱和手机立即绑定

如何在批处理文件中获得字符串长度?

/ 猿问

如何在批处理文件中获得字符串长度?

慕丝7291255 2019-07-20 10:04:40

如何在批处理文件中获得字符串长度?

在批处理文件中获取字符串的长度似乎没有一种简单的方法。例如,

SET MY_STRING=abcdefg
SET /A MY_STRING_LEN=???

的字符串长度如何查找?MY_STRING?

如果字符串长度函数处理字符串中的所有可能字符(包括转义字符),则加分如下:!%^^()^!.


查看完整描述

3 回答

?
白衣染霜花

由于没有针对字符串长度的内置函数,您可以编写自己的函数,如下所示:

@echo off
setlocal
set "myString=abcdef!%%^^()^!"
call :strlen result myString
echo %result%
goto :eof

:strlen <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
)

这个函数总是需要13个循环,而不是一个简单的strlen函数,它需要strlen循环。
它处理所有字符。


查看完整回答
反对 回复 2019-07-20
?
犯罪嫌疑人X

您可以通过将字符串写入文件,然后获取文件的长度,在批处理文件中执行两行操作。您只需减去两个字节,就可以计算添加到末尾的自动CR+LF。

假设您的字符串位于一个名为strvar:

ECHO %strvar%> tempfile.txt
FOR %%? IN (tempfile.txt) DO ( SET /A strlength=%%~z? - 2 )

字符串的长度现在位于一个名为strlength.

更详细的是:

  • FOR %%? IN (filename) DO ( ...

    获取有关文件的信息
  • SET /A [variable]=[expression]

    *对表达式进行数值计算
  • %%~z?

    *获取文件长度的特殊表达式

要将整个命令混成一行:

ECHO %strvar%>x&FOR %%? IN (x) DO SET /A strlength=%%~z? - 2&del x


查看完整回答
反对 回复 2019-07-20
?
噜噜哒

(实际上,在DosTips上还有一些附加的优化,但我认为它们不值得这样做)

但是,提出新的高效算法是很有趣的。下面是一个使用FINDSTR/O选项的新算法:

@echo off
setlocal
set "test=Hello world!"

:: Echo the length of TEST
call :strLen test

:: Store the length of TEST in LEN
call :strLen test len
echo len=%len%
exit /b

:strLen  strVar  [rtnVar]
setlocal disableDelayedExpansion
set len=0
if defined %~1 for /f "delims=:" %%N in (
  '"(cmd /v:on /c echo(!%~1!&echo()|findstr /o ^^"'
) do set /a "len=%%N-3"
endlocal & if "%~2" neq "" (set %~2=%len%) else echo %len%
exit /b

代码减去3,因为解析器会在CMD/V/C执行命令之前修改命令并添加一个空格。它可以通过使用(echo(!%~1!^^^).


对于那些想要绝对最快表现的人来说,杰布的回答可以作为批处理带有参数的宏..这是在DosTips开发的一种先进的批处理技术,它消除了调用a:子例程的固有的缓慢过程。你可以这里有更多关于批处理宏背后概念的背景知识。,但该链接使用了一种更原始、不那么理想的语法。

下面是一个优化的@strLen宏,示例显示宏和:子例程用法之间的差异,以及性能上的差异。

@echo off
setlocal disableDelayedExpansion

:: -------- Begin macro definitions ----------
set ^"LF=^
%= This creates a variable containing a single linefeed (0x0A) character =%
^"
:: Define %\n% to effectively issue a newline with line continuation
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"

:: @strLen  StrVar  [RtnVar]
::
::   Computes the length of string in variable StrVar
::   and stores the result in variable RtnVar.
::   If RtnVar is is not specified, then prints the length to stdout.
::
set @strLen=for %%. in (1 2) do if %%.==2 (%\n%
  for /f "tokens=1,2 delims=, " %%1 in ("!argv!") do ( endlocal%\n%
    set "s=A!%%~1!"%\n%
    set "len=0"%\n%
    for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (%\n%
      if "!s:~%%P,1!" neq "" (%\n%
        set /a "len+=%%P"%\n%
        set "s=!s:~%%P!"%\n%
      )%\n%
    )%\n%
    for %%V in (!len!) do endlocal^&if "%%~2" neq "" (set "%%~2=%%V") else echo %%V%\n%
  )%\n%
) else setlocal enableDelayedExpansion^&setlocal^&set argv=,

:: -------- End macro definitions ----------

:: Print out definition of macro
set @strLen

:: Demonstrate usage

set "testString=this has a length of 23"

echo(
echo Testing %%@strLen%% testString
%@strLen% testString

echo(
echo Testing call :strLen testString
call :strLen testString

echo(
echo Testing %%@strLen%% testString rtn
set "rtn="
%@strLen% testString rtn
echo rtn=%rtn%

echo(
echo Testing call :strLen testString rtn
set "rtn="
call :strLen testString rtn
echo rtn=%rtn%

echo(
echo Measuring %%@strLen%% time:
set "t0=%time%"
for /l %%N in (1 1 1000) do %@strlen% testString testLength
set "t1=%time%"
call :printTime

echo(
echo Measuring CALL :strLen time:
set "t0=%time%"
for /l %%N in (1 1 1000) do call :strLen testString testLength
set "t1=%time%"
call :printTime
exit /b


:strlen  StrVar  [RtnVar]
::
:: Computes the length of string in variable StrVar
:: and stores the result in variable RtnVar.
:: If RtnVar is is not specified, then prints the length to stdout.
::
(
  setlocal EnableDelayedExpansion
  set "s=A!%~1!"
  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
  if "%~2" equ "" (echo %len%) else set "%~2=%len%"
  exit /b
)

:printTime
setlocal
for /f "tokens=1-4 delims=:.," %%a in ("%t0: =0%") do set /a "t0=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100
for /f "tokens=1-4 delims=:.," %%a in ("%t1: =0%") do set /a "t1=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100
set /a tm=t1-t0
if %tm% lss 0 set /a tm+=24*60*60*100
echo %tm:~0,-2%.%tm:~-2% msec
exit /b

-样本输出-

@strLen=for %. in (1 2) do if %.==2 (
  for /f "tokens=1,2 delims=, " %1 in ("!argv!") do ( endlocal
    set "s=A!%~1!"
    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!"
      )
    )
    for %V in (!len!) do endlocal&if "%~2" neq "" (set "%~2=%V") else echo %V
  )
) else setlocal enableDelayedExpansion&setlocal&set argv=,

Testing %@strLen% testString
23

Testing call :strLen testString
23

Testing %@strLen% testString rtn
rtn=23

Testing call :strLen testString rtn
rtn=23

Measuring %@strLen% time:
1.93 msec

Measuring CALL :strLen time:
7.08 msec


查看完整回答
反对 回复 2019-07-20
  • 3 回答
  • 0 关注
  • 7100 浏览
我要回答
慕课专栏
更多

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信