首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在批处理文件中获取字符串长度?

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

Stack Overflow用户
提问于 2011-04-30 05:08:17
回答 18查看 173.3K关注 0票数 70

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

代码语言:javascript
复制
SET MY_STRING=abcdefg
SET /A MY_STRING_LEN=???

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

如果string length函数处理字符串中所有可能的字符,包括转义字符,就会得到加分,比如:!%^^()^!

EN

回答 18

Stack Overflow用户

回答已采纳

发布于 2011-04-30 20:01:48

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

代码语言:javascript
复制
@echo off
setlocal
REM *** Some tests, to check the functionality ***
REM *** An emptyStr has the length 0
set "emptyString="
call :strlen result emptyString
echo %result%

REM *** This string has the length 14
set "myString=abcdef!%%^^()^!"
call :strlen result myString
echo %result%

REM *** This string has the maximum length of 8191
setlocal EnableDelayedExpansion
set "long=."
FOR /L %%n in (1 1 13) DO set "long=!long:~-4000!!long:~-4000!"
(set^ longString=!long!!long:~-191!)

call :strlen result longString
echo %result%

goto :eof

REM ********* function *****************************
:strlen <resultVar> <stringVar>
(   
    setlocal EnableDelayedExpansion
    (set^ tmp=!%~2!)
    if defined tmp (
        set "len=1"
        for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
            if "!tmp:~%%P,1!" NEQ "" ( 
                set /a "len+=%%P"
                set "tmp=!tmp:~%%P!"
            )
        )
    ) ELSE (
        set len=0
    )
)
( 
    endlocal
    set "%~1=%len%"
    exit /b
)

这个函数需要13个循环,而不是一个需要strlen -loop的简单strlen函数。

它可以处理所有字符。

奇怪的表达式(set^ tmp=!%~2!)是处理超长字符串所必需的,否则就不可能复制它们。

票数 91
EN

Stack Overflow用户

发布于 2011-12-20 02:54:30

通过将字符串写入文件,然后获取文件的长度,可以在批处理文件中完整地使用两行代码。您只需减去两个字节即可计算添加到末尾的自动CR+LF。

假设您的字符串在一个名为strvar的变量中

代码语言:javascript
复制
ECHO %strvar%> tempfile.txt
FOR %%? IN (tempfile.txt) DO ( SET /A strlength=%%~z? - 2 )

字符串的长度现在位于一个名为strlength的变量中。

更详细地说:

  • FOR %%? IN (filename) DO ( ...:获取有关file
  • SET /A [variable]=[expression]的信息:计算表达式numerically
  • %%~z?:特殊表达式以获取文件的长度

要在一行中合并整个命令,请执行以下操作:

代码语言:javascript
复制
ECHO %strvar%>x&FOR %%? IN (x) DO SET /A strlength=%%~z? - 2&del x
票数 36
EN

Stack Overflow用户

发布于 2012-12-18 07:44:45

我更喜欢jeb's accepted answer -它是已知的最快的解决方案,也是我在自己的脚本中使用的解决方案。(实际上在DosTips上流传着一些额外的优化,但我认为它们不值得)

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

代码语言:javascript
复制
@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!^^^)来预防。

对于那些想要尽可能获得最快性能的人,可以采用jeb's answer作为batch "macro" with arguments。这是在DosTips上开发的一种高级批处理技术,它消除了CALLing a:子例程固有的缓慢进程。您可以获得more background on the concepts behind batch macros here,但该链接使用了更原始、更不可取的语法。

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

代码语言:javascript
复制
@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

--示例输出--

代码语言:javascript
复制
@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
票数 23
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5837418

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档