ProgramingTip

배치 파일에서 어디에서 길이를 어떻게 얻습니까?

bestdevel 2020. 11. 26. 19:41
반응형

배치 파일에서 어디에서 길이를 어떻게 얻습니까?


배치 파일에서 용이 한 길이를 얻을 수 있습니다. 예 :

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

-length를 문자열 MY_STRING어떻게 찾을 수 있습니까?

이스케이프 길이 함수가 다음과 같이 이스케이프 문자를 포함하여 많은 것에서 가능한 모든 문자를 처리하는 경우 포인트가 제공 !%^^()^!됩니다.


이미있는 길이에 대한 내장 함수가 내부 다음과 같이 고유 한 함수를 사용할 수 있습니다.

@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
)

이 함수는 strlen 루프가 필요한 단순한 strlen 함수 대신 항상 13 개의 루프가 필요합니다.
모든 문자를 처리합니다.

(set^ tmp=!%~2!)매우 긴 발송을 처리해야하는 이상한 표현 이 필요합니다. 텍스트 복사 할 수 없습니다.


이전 파일에 쓴 다음 파일의 길이를 가져 오기 두 줄로 전체 배치 파일로 수행 할 수 있습니다. 끝에 추가 된 자동 CR + LF를 설명하기 위해 2 바이트를 빼면됩니다.

가정 해 보겠습니다 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

나는 jeb의 허용되는 솔루션 선호합니다 . (실제로 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

파서가 명령을 저글링하고 CMD / V / C가 명령을 실행하기 전에 공백을 추가하기 때문에 코드는 3을 부담니다. 를 사용하여 예방할 수 있습니다 (echo(!%~1!^^^).


가능한 절대적으로 가장 빠른 성능을 원하는 사람들을 위해 jeb의 대답을 인수와 함께 배치 "매크로"로 사용할 수 있습니다 . 이것은 서브 루틴을 호출하는 내부적으로 느린 프로세스를 제거하는 DosTips에서 개발 된 고급 배치 기술입니다. 여기 에서 배치 매크로의 개념에 대한 더 많은 배경 정보를 얻을 수있는 링크는 더 원시적 인 덜 바람직한 구문을 사용합니다.

아래는 최적화 된 @strLen 매크로로, 매크로와 : subroutine 사용의 차이점과 성능 차이를 그래픽 예제입니다.

@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


처음 몇 줄은 표시 : strLen 함수를 보여주기위한 것입니다.

@echo off
set "strToMeasure=This is a string"
call :strLen strToMeasure strlen
echo.String is %strlen% characters long
exit /b

:strLen
setlocal enabledelayedexpansion
:strLen_Loop
  if not "!%1:~%len%!"=="" set /A len+=1 & goto :strLen_Loop
(endlocal & set %2=%len%)
goto :eof

물론 이것은 jeb에서 제공하는 "13 loop"버전에서 그다지 처음으로 사용합니다. 그러나 이해하기가 더 복잡한 3GHz 컴퓨터는 몇 분의 1 초 안에 수천 번의 반복을 통과 할 수 있습니다.


예, 물론 vbscript (또는 powershell)를 사용하는 쉬운 방법이 있습니다.

WScript.Echo Len( WScript.Arguments(0) )

명령 strlen.vbs줄에 저장

c:\test> cscript //nologo strlen.vbs "abcd"

for 루프를 사용하여 결과적으로 사용 (또는 스크립팅 작업에 vbscript 전적으로 사용)

배치를 사용하여 번거로운 해결 방법을 더 좋으며 vbscript는 각 Windows 배포 (및 나중에 powershell)에서 사용할 수 있기 때문에 사용할 수 없습니다.


방금 ULTIMATE 솔루션을 찾았습니다.

set "MYSTRING=abcdef!%%^^()^!"
(echo "%MYSTRING%" & echo.) | findstr /O . | more +1 | (set /P RESULT= & call exit /B %%RESULT%%)
set /A STRLENGTH=%ERRORLEVEL%-5
echo string "%MYSTRING%" length = %STRLENGTH%

출력은 다음과 가변합니다.

string "abcdef!%^^()^!" length = 14

이스케이프 문자를 처리하며 위의 대부분의 솔루션보다 훨씬 간단하며 루프, 매직 넘버, DelayedExpansion, 임시 파일 등을 포함하지 않습니다.

배치 펼쳐 외부에서 사용하는 경우 (명령을 콘솔에 수동으로 넣는 것을 의미 함) 키 %%RESULT%%%RESULT%.

필요한 경우 NOP 명령 %ERRORLEVEL%FALSE사용하여 변수를 접근 할 수 있습니다.echo. >nul


Windows Vista +를 사용하는 경우 다음 Powershell 방법을 시도하십시오.

For /F %%L in ('Powershell $Env:MY_STRING.Length') do (
    Set MY_STRING_LEN=%%L
)

또는 대안으로 :

Powershell $Env:MY_STRING.Length > %Temp%\TmpFile.txt
Set /p MY_STRING_LEN = < %Temp%\TmpFile.txt
Del %Temp%\TmpFile.txt

나는 Windows 7 x64를 사용하고 있으며 이것은 나를 위해 일하고 있습니다.


jmh_gr 두 줄 접근 방식 을 좋아합니다.

()리디렉션 전에 명령 부분을 둘러싼 경우 가 아니면 한 자리 숫자로 작동하지 않습니다 . 이후 1>특별한 명령은 파일로 리디렉션됩니다.

이 예제는 한 자리 숫자를 처리해야 할 때 <사용할 수 있는 기타 특수 문자는 처리하지 않습니다 .

(ECHO %strvar%)> tempfile.txt

단 몇 줄의 확장 길이를 계산하는 또 다른 배치 펼쳐집니다. 가장 빠르지는 않지만 꽤 작습니다. 서브 루틴 ": len"은 두 번째 매개 변수의 길이를 리턴합니다. 첫 번째 번째 매개 변수는 분석되는 문자열입니다. 참고-특수 문자는 이스케이프되어야합니다. 즉, 배치 파일의 많은이있는 경우입니다.

@echo off
setlocal
call :len "Sample text" a
echo The string has %a% characters.
endlocal
goto :eof

:len <string> <length_variable> - note: string must be quoted because it may have spaces
setlocal enabledelayedexpansion&set l=0&set str=%~1
:len_loop
set x=!str:~%l%,1!&if not defined x (endlocal&set "%~2=%l%"&goto :eof)
set /a l=%l%+1&goto :len_loop

@echo off & setlocal EnableDelayedExpansion
set Var=finding the length of strings
for /l %%A in (0,1,10000) do if not "%Var%"=="!Var:~0,%%A!" (set /a Length+=1) else (echo !Length! & pause & exit /b)

var =로 변경하여 사용자가 입력합니다. 나중에 참조 할 수 있도록 여기에 넣습니다.


@echo off
::   warning doesn't like * ( in mystring

setlocal enabledelayedexpansion 

set mystring=this is my string to be counted forty one

call :getsize %mystring%
echo count=%count% of "%mystring%" 

set mystring=this is my string to be counted

call :getsize %mystring%

echo count=%count% of "%mystring%" 

set mystring=this is my string
call :getsize %mystring%

echo count=%count% of "%mystring%" 
echo.
pause
goto :eof

:: Get length of mystring line ######### subroutine getsize ########

:getsize

set count=0

for /l %%n in (0,1,2000) do (

    set chars=

    set chars=!mystring:~%%n!

    if defined chars set /a count+=1
)
goto :eof

:: ############## end of subroutine getsize ########################

나는 코드를 / 펼쳐 / 등을 작성하는 것을 많이 알고 말하면서 시작하고 싶습니다. 그러나 내가 생각해 낸 것 같은 해결책을 공유 할 생각했습니다. 여기에있는 대부분의 답변은 제 머릿속을 넘어서서 제가 쓴 내용이 지 궁금했습니다.

@echo off

set stringLength=0

call:stringEater "It counts most characters"
echo %stringLength%
echo.&pause&goto:eof

:stringEater
set var=%~1
:subString
set n=%var:~0,1%
if "%n%"=="" (
        goto:eof
    ) else if "%n%"==" " (
        set /a stringLength=%stringLength%+1
    ) else (
        set /a stringLength=%stringLength%+1
    )
set var=%var:~1,1000%
if "%var%"=="" (
        goto:eof
    ) else (
        goto subString
    )

goto:eof

그것은 훨씬 더 간단합니다 !

순수한 배치 솔루션. 임시 파일이 없습니다. 긴 펼쳐지지 않습니다.

@echo off
setlocal enabledelayedexpansion
set String=abcde12345

for /L %%x in (1,1,1000) do ( if "!String:~%%x!"=="" set Lenght=%%x & goto Result )

:Result 
echo Lenght: !Lenght!

1000예상되는 최대 확장 길이입니다. 필요에 따라 변경하십시오.


@ECHO OFF

SET string=
SET /A stringLength=0

:CheckNextLetter
REM Subtract the first letter and count up until the string="".
IF "%string%" NEQ "" (
    SET string=%string:~1%
    SET /A stringLength=%stringLength%+1
    GOTO :CheckNextLetter
) ELSE (
    GOTO :TheEnd
)

:TheEnd
    ECHO There is %stringLength% character^(s^) in the string.
PAUSE

이것은 나를 위해 작동합니다. 이것이 다른 사람에게 유용하기를 바랍니다. 길이가 필요 없습니다. 첫 번째 문자를 제거하고 제거하고 ""가 될 때까지 ""와 비교합니다.

참고 URL : https://stackoverflow.com/questions/5837418/how-do-you-get-the-string-length-in-a-batch-file

반응형