Windows(cmd)批处理-在子例程中使用括号

d7v8vwbk  于 2023-10-22  发布在  Windows
关注(0)|答案(1)|浏览(126)

我经常在:LABEL中看到括号( ... )的示意图。
我读了圆括号/方括号,但我不太明白如何在子例程中解释这一点。
(例如https://ss64.com/nt/syntax-brackets.html

使用括号内的变量

  • CMD shell将扩展[读入内存]代码块开头的所有变量,并使用这些值,即使变量的值在代码块中发生了更改。打开DelayedExpansion将强制shell在每行的开头读取变量。*

不幸的是,我在互联网上找不到对调用或子例程的具体描述。
(例如https://ss64.com/nt/call.htmlhttps://ss64.com/nt/syntax-functions.html
我想知道它是否只是一种代码风格(例如,(这是我目前的猜测。
举个简单的例子:

@ECHO OFF

CALL :ShortLabel
CALL :LongLabel
GOTO :EndOfBatch

:ShortLabel
ECHO I'm called "%~0" .
EXIT /B

:LongLabel
(
   ECHO I'm called "%~0" , because I have two extra lines.
   EXIT /B
)

:EndOfBatch
PAUSE
EXIT /B

如果没有,我希望你能简要解释一下。

更新:

由于我以前的“时间测量”是垃圾,这里有一个更好的版本(我希望)。第一个调用只是复制粘贴出第二个括号:

@ECHO OFF

SETLOCAL EnableExtensions EnableDelayedExpansion

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

SET /A Loops=3000

TITLE A - StrLenNoLocal
CALL :TimeStamp StrLenNoLocalStart
FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenNoLocal LenDummyStrLenNoLocalA string %%a
CALL :TimeStamp StrLenNoLocalEnd

TITLE A - StrLenNoLocalBrackets
CALL :TimeStamp StrLenNoLocalBracketsStart
FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenNoLocalBrackets LenDummyStrLenNoLocalBracketsA string %%a
CALL :TimeStamp StrLenNoLocalBracketsEnd

TITLE A - StrLenLocal
CALL :TimeStamp StrLenLocalStart
FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenLocal LenDummyStrLenLocalA string %%a
CALL :TimeStamp StrLenLocalEnd

TITLE A - StrLenLocalBrackets
CALL :TimeStamp StrLenLocalBracketsStart
FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenLocalBrackets LenDummyStrLenLocalBracketsA string %%a
CALL :TimeStamp StrLenLocalBracketsEnd

CALL :MeasureTime StrLenNoLocalTime StrLenNoLocalStart StrLenNoLocalEnd
CALL :MeasureTime StrLenNoLocalBracketsTime StrLenNoLocalBracketsStart StrLenNoLocalBracketsEnd
CALL :MeasureTime StrLenLocalTime StrLenLocalStart StrLenLocalEnd
CALL :MeasureTime StrLenLocalBracketsTime StrLenLocalBracketsStart StrLenLocalBracketsEnd

REM Invert order

TITLE B - StrLenLocalBrackets
CALL :TimeStamp StrLenLocalBracketsStart
FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenLocalBrackets LenDummyStrLenLocalBracketsB string %%a
CALL :TimeStamp StrLenLocalBracketsEnd

TITLE B - StrLenLocal
CALL :TimeStamp StrLenLocalStart
FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenLocal LenDummyStrLenLocalB string %%a
CALL :TimeStamp StrLenLocalEnd

TITLE B - StrLenNoLocalBrackets
CALL :TimeStamp StrLenNoLocalBracketsStart
FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenNoLocalBrackets LenDummyStrLenNoLocalBracketsB string %%a
CALL :TimeStamp StrLenNoLocalBracketsEnd

TITLE B - StrLenNoLocal
CALL :TimeStamp StrLenNoLocalStart
FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenNoLocal LenDummyStrLenNoLocalB string %%a
CALL :TimeStamp StrLenNoLocalEnd

TITLE Results
ECHO.

ECHO Time StrLenNoLocal          A :  !StrLenNoLocalTime!
ECHO Time StrLenNoLocalBrackets  A :  !StrLenNoLocalBracketsTime!
ECHO Time StrLenLocal            A :  !StrLenLocalTime!
ECHO Time StrLenLocalBrackets    A :  !StrLenLocalBracketsTime!
ECHO StrLen !LenDummyStrLenNoLocalA! / !LenDummyStrLenNoLocalBracketsA! / !LenDummyStrLenLocalA! / !LenDummyStrLenLocalBracketsA!
ECHO.

CALL :MeasureTime StrLenNoLocalTime StrLenNoLocalStart StrLenNoLocalEnd
CALL :MeasureTime StrLenNoLocalBracketsTime StrLenNoLocalBracketsStart StrLenNoLocalBracketsEnd
CALL :MeasureTime StrLenLocalTime StrLenLocalStart StrLenLocalEnd
CALL :MeasureTime StrLenLocalBracketsTime StrLenLocalBracketsStart StrLenLocalBracketsEnd

ECHO Time StrLenNoLocal          B :  !StrLenNoLocalTime!
ECHO Time StrLenNoLocalBrackets  B :  !StrLenNoLocalBracketsTime!
ECHO Time StrLenLocal            B :  !StrLenLocalTime!
ECHO Time StrLenLocalBrackets    B :  !StrLenLocalBracketsTime!
ECHO StrLen !LenDummyStrLenNoLocalB! / !LenDummyStrLenNoLocalBracketsB! / !LenDummyStrLenLocalB! / !LenDummyStrLenLocalBracketsB!
ECHO.

GOTO :EndOfBatch

REM https://stackoverflow.com/a/5841587/1378342
REM The original "function" is missing the /A for a number twice, which is wrong in my opinion. It seems to speed up the output.
REM I also added missing cosmetic double quotes for "set" to make it more accurate

:StrLenNoLocal
ECHO Loop %~3 / %Loops%
(SET^ tmp=!%~2!)
IF DEFINED tmp (
  SET /A "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 /A "len=0"
)
SET /A "%~1=!len!"
EXIT /B

:StrLenNoLocalBrackets
(
   ECHO Loop %~3 / %Loops%
   (SET^ tmp=!%~2!)
   IF DEFINED tmp (
      SET /A "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 /A "len=0"
   )
   SET /A "%~1=!len!"
   EXIT /B
)

:StrLenLocal
echo Loop %~3 / %Loops% & setlocal EnableDelayedExpansion & (set^ tmp=!%~2!)
if defined tmp (
  set /a "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 /a "len=0"
)
endlocal & set /a "%~1=%len%" & exit /b

:StrLenLocalBrackets
(
   echo Loop %~3 / %Loops%
)
(
   setlocal EnableDelayedExpansion
   (set^ tmp=!%~2!)
   if defined tmp (
      set /a "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 /a "len=0"
   )
)
(
   endlocal
   set /a "%~1=%len%"
   exit /b
)


:TimeStamp
SET /A %~1=1%time:~-5,-3%%time:~-2%
EXIT /B

:MeasureTime
SET /A %~1=!%~3!-!%~2!
IF !%~1! LSS 0 SET /A %~1=6000+!%~1!
SET %~1=!%~1:~0,-2!.!%~1:~-2!sec
EXIT /B


:EndOfBatch
PAUSE
ENDLOCAL
GOTO :EOF

输出量:

Time StrLenNoLocal          A :  17.57sec
Time StrLenNoLocalBrackets  A :  15.06sec
Time StrLenLocal            A :  17.70sec
Time StrLenLocalBrackets    A :  18.09sec
StrLen 8191 / 8191 / 8191 / 8191

Time StrLenNoLocal          B :  17.05sec
Time StrLenNoLocalBrackets  B :  14.56sec
Time StrLenLocal            B :  17.39sec
Time StrLenLocalBrackets    B :  17.84sec
StrLen 8191 / 8191 / 8191 / 8191

( ... )版本比较快。
只要大家没有异议,我的结论是:
我更喜欢行数少的代码,只要它不影响可读性。* 但是 * 如果这两个括号可以使脚本更快一点,而且不会造成任何伤害-为什么不呢?;)

rsl1atfo

rsl1atfo1#

在“如果”之后...

  • 我的措施毫无意义
  • 我测量超时/ ping
  • 我把所有的东西都放在括号里
  • 我调用方括号内的嵌套标签

思考:

@ECHO OFF

SETLOCAL EnableExtensions EnableDelayedExpansion

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

SET /A Loops=3000

TITLE A - StrLenNoLocal
CALL :TimeStamp StrLenNoLocalStart
FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenNoLocal LenDummyStrLenNoLocalA string %%a
CALL :TimeStamp StrLenNoLocalEnd

TITLE A - StrLenNoLocalBrackets
CALL :TimeStamp StrLenNoLocalBracketsStart
FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenNoLocalBrackets LenDummyStrLenNoLocalBracketsA string %%a
CALL :TimeStamp StrLenNoLocalBracketsEnd

TITLE A - StrLenLocal
CALL :TimeStamp StrLenLocalStart
FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenLocal LenDummyStrLenLocalA string %%a
CALL :TimeStamp StrLenLocalEnd

TITLE A - StrLenLocalBrackets
CALL :TimeStamp StrLenLocalBracketsStart
FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenLocalBrackets LenDummyStrLenLocalBracketsA string %%a
CALL :TimeStamp StrLenLocalBracketsEnd

CALL :MeasureTime StrLenNoLocalTime StrLenNoLocalStart StrLenNoLocalEnd
CALL :MeasureTime StrLenNoLocalBracketsTime StrLenNoLocalBracketsStart StrLenNoLocalBracketsEnd
CALL :MeasureTime StrLenLocalTime StrLenLocalStart StrLenLocalEnd
CALL :MeasureTime StrLenLocalBracketsTime StrLenLocalBracketsStart StrLenLocalBracketsEnd

REM Messure Timeout 5sec
TITLE Timeout 5sec
CALL :TimeStamp TimeoutStart
timeout /NOBREAK /T 5 >NUL
CALL :TimeStamp TimeoutEnd
CALL :MeasureTime TimeoutTime TimeoutStart TimeoutEnd

REM Ping...
TITLE Ping 5000
CALL :TimeStamp PingStart
ping 1.2.3.4 -n 1 -w 5000 >NUL
CALL :TimeStamp PingEnd
CALL :MeasureTime PingTime PingStart PingEnd

REM Ping 50 * 100
TITLE PingOneHundredTimes
CALL :TimeStamp PingOneHundredTimesStart
CALL :PingOneHundredTimes
CALL :TimeStamp PingOneHundredTimesEnd

TITLE PingOneHundredTimesBrackets
CALL :TimeStamp PingOneHundredTimesBracketsStart
CALL :PingOneHundredTimesBrackets
CALL :TimeStamp PingOneHundredTimesBracketsEnd

CALL :MeasureTime PingOneHundredTimesTime PingOneHundredTimesStart PingOneHundredTimesEnd
CALL :MeasureTime PingOneHundredTimesBracketsTime PingOneHundredTimesBracketsStart PingOneHundredTimesBracketsEnd

REM Invert order

TITLE B - StrLenLocalBrackets
CALL :TimeStamp StrLenLocalBracketsStart
FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenLocalBrackets LenDummyStrLenLocalBracketsB string %%a
CALL :TimeStamp StrLenLocalBracketsEnd

TITLE B - StrLenLocal
CALL :TimeStamp StrLenLocalStart
FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenLocal LenDummyStrLenLocalB string %%a
CALL :TimeStamp StrLenLocalEnd

TITLE B - StrLenNoLocalBrackets
CALL :TimeStamp StrLenNoLocalBracketsStart
FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenNoLocalBrackets LenDummyStrLenNoLocalBracketsB string %%a
CALL :TimeStamp StrLenNoLocalBracketsEnd

TITLE B - StrLenNoLocal
CALL :TimeStamp StrLenNoLocalStart
FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenNoLocal LenDummyStrLenNoLocalB string %%a
CALL :TimeStamp StrLenNoLocalEnd

TITLE Results
ECHO.

REM "Empty" Timestamp Measure
CALL :TimeStamp TimestampStart
CALL :TimeStamp TimestampEnd
CALL :MeasureTime TimestampTime TimestampStart TimestampEnd

ECHO Time StrLenNoLocal          A :  !StrLenNoLocalTime!
ECHO Time StrLenNoLocalBrackets  A :  !StrLenNoLocalBracketsTime!
ECHO Time StrLenLocal            A :  !StrLenLocalTime!
ECHO Time StrLenLocalBrackets    A :  !StrLenLocalBracketsTime!
ECHO StrLen !LenDummyStrLenNoLocalA! / !LenDummyStrLenNoLocalBracketsA! / !LenDummyStrLenLocalA! / !LenDummyStrLenLocalBracketsA!
ECHO.

CALL :MeasureTime StrLenNoLocalTime StrLenNoLocalStart StrLenNoLocalEnd
CALL :MeasureTime StrLenNoLocalBracketsTime StrLenNoLocalBracketsStart StrLenNoLocalBracketsEnd
CALL :MeasureTime StrLenLocalTime StrLenLocalStart StrLenLocalEnd
CALL :MeasureTime StrLenLocalBracketsTime StrLenLocalBracketsStart StrLenLocalBracketsEnd

ECHO Time StrLenNoLocal          B :  !StrLenNoLocalTime!
ECHO Time StrLenNoLocalBrackets  B :  !StrLenNoLocalBracketsTime!
ECHO Time StrLenLocal            B :  !StrLenLocalTime!
ECHO Time StrLenLocalBrackets    B :  !StrLenLocalBracketsTime!
ECHO StrLen !LenDummyStrLenNoLocalB! / !LenDummyStrLenNoLocalBracketsB! / !LenDummyStrLenLocalB! / !LenDummyStrLenLocalBracketsB!
ECHO.
ECHO "Empty" Timestamp Measure   :  !TimestampTime!
ECHO Timeout /T 5                :  !TimeoutTime!
ECHO ping 1.2.3.4 -n 1 -w 5000   :  !PingTime!
ECHO PingOneHundredTimes         :  !PingOneHundredTimesTime!
ECHO PingOneHundredTimesBrackets :  !PingOneHundredTimesBracketsTime!
ECHO.

SET AREYOUSURE=n
SET /P "AREYOUSURE=Do you like to start over again inside brackets (y/[n]) ? "
IF /I "!AREYOUSURE!" EQU "y" CALL :DoItAgain

REM Test if labels inside brackets still works...

REM Label inside a Label with brackets
ECHO.
CALL :LabelBrackets
CALL :LabelInsideLabelBrackets
ECHO.
REM Label inside a Label with brackets without Exit after LabelBracketsWOExit
CALL :LabelBracketsWOExit
CALL :LabelInsideLabelBracketsWOExit
ECHO.


GOTO :EndOfBatch

REM https://stackoverflow.com/a/5841587/1378342
REM The original "function" is missing the /A for a number twice, which is wrong in my opinion. It seems to speed up the output.
REM I also added missing cosmetic double quotes for "set" to make it more accurate

:StrLenNoLocal
ECHO Loop %~3 / %Loops%
(SET^ tmp=!%~2!)
IF DEFINED tmp (
  SET /A "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 /A "len=0"
)
SET /A "%~1=!len!"
EXIT /B

:StrLenNoLocalBrackets
(
   ECHO Loop %~3 / %Loops%
   (SET^ tmp=!%~2!)
   IF DEFINED tmp (
      SET /A "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 /A "len=0"
   )
   SET /A "%~1=!len!"
   EXIT /B
)

:StrLenLocal
echo Loop %~3 / %Loops% & setlocal EnableDelayedExpansion & (set^ tmp=!%~2!)
if defined tmp (
  set /a "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 /a "len=0"
)
endlocal & set /a "%~1=%len%" & exit /b

:StrLenLocalBrackets
(
   echo Loop %~3 / %Loops%
)
(
   setlocal EnableDelayedExpansion
   (set^ tmp=!%~2!)
   if defined tmp (
      set /a "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 /a "len=0"
   )
)
(
   endlocal
   set /a "%~1=%len%"
   exit /b
)


:TimeStamp
SET /A %~1=1%time:~-5,-3%%time:~-2%
EXIT /B

:MeasureTime
SET /A %~1=!%~3!-!%~2!
IF !%~1! LSS 0 SET /A %~1=6000+!%~1!
IF "!%~1:~-2,-1!" == "" SET %~1=0!%~1!
IF "!%~1:~0,-2!" == "" SET %~1=0!%~1!
SET %~1=!%~1:~0,-2!.!%~1:~-2!sec
EXIT /B


:EndOfBatch
ENDLOCAL
GOTO :EOF


:LabelBrackets
(
   ECHO I'm called "%~0" .
   EXIT /B
   :LabelInsideLabelBrackets
   ECHO I'm called "%~0" .
   EXIT /B
)

:LabelBracketsWOExit
(
   ECHO I'm called "%~0" .
   :LabelInsideLabelBracketsWOExit
   ECHO I'm called "%~0" .
   EXIT /B
)


:PingOneHundredTimes
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
ping 1.2.3.4 -n 1 -w 50 >NUL
EXIT /B

:PingOneHundredTimesBrackets
(
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   ping 1.2.3.4 -n 1 -w 50 >NUL
   EXIT /B
)


:DoItAgain
(
    TITLE A - StrLenNoLocal
    CALL :TimeStamp StrLenNoLocalStart
    FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenNoLocal LenDummyStrLenNoLocalA string %%a
    CALL :TimeStamp StrLenNoLocalEnd

    TITLE A - StrLenNoLocalBrackets
    CALL :TimeStamp StrLenNoLocalBracketsStart
    FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenNoLocalBrackets LenDummyStrLenNoLocalBracketsA string %%a
    CALL :TimeStamp StrLenNoLocalBracketsEnd

    TITLE A - StrLenLocal
    CALL :TimeStamp StrLenLocalStart
    FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenLocal LenDummyStrLenLocalA string %%a
    CALL :TimeStamp StrLenLocalEnd

    TITLE A - StrLenLocalBrackets
    CALL :TimeStamp StrLenLocalBracketsStart
    FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenLocalBrackets LenDummyStrLenLocalBracketsA string %%a
    CALL :TimeStamp StrLenLocalBracketsEnd

    CALL :MeasureTime StrLenNoLocalTime StrLenNoLocalStart StrLenNoLocalEnd
    CALL :MeasureTime StrLenNoLocalBracketsTime StrLenNoLocalBracketsStart StrLenNoLocalBracketsEnd
    CALL :MeasureTime StrLenLocalTime StrLenLocalStart StrLenLocalEnd
    CALL :MeasureTime StrLenLocalBracketsTime StrLenLocalBracketsStart StrLenLocalBracketsEnd

    REM Messure Timeout 5sec
    TITLE Timeout 5sec
    CALL :TimeStamp TimeoutStart
    timeout /NOBREAK /T 5 >NUL
    CALL :TimeStamp TimeoutEnd
    CALL :MeasureTime TimeoutTime TimeoutStart TimeoutEnd

    REM Ping...
    TITLE Ping 5000
    CALL :TimeStamp PingStart
    ping 1.2.3.4 -n 1 -w 5000 >NUL
    CALL :TimeStamp PingEnd
    CALL :MeasureTime PingTime PingStart PingEnd

    REM Ping 50 * 100
    TITLE PingOneHundredTimes
    CALL :TimeStamp PingOneHundredTimesStart
    CALL :PingOneHundredTimes
    CALL :TimeStamp PingOneHundredTimesEnd

    TITLE PingOneHundredTimesBrackets
    CALL :TimeStamp PingOneHundredTimesBracketsStart
    CALL :PingOneHundredTimesBrackets
    CALL :TimeStamp PingOneHundredTimesBracketsEnd

    CALL :MeasureTime PingOneHundredTimesTime PingOneHundredTimesStart PingOneHundredTimesEnd
    CALL :MeasureTime PingOneHundredTimesBracketsTime PingOneHundredTimesBracketsStart PingOneHundredTimesBracketsEnd

    REM Invert order

    TITLE B - StrLenLocalBrackets
    CALL :TimeStamp StrLenLocalBracketsStart
    FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenLocalBrackets LenDummyStrLenLocalBracketsB string %%a
    CALL :TimeStamp StrLenLocalBracketsEnd

    TITLE B - StrLenLocal
    CALL :TimeStamp StrLenLocalStart
    FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenLocal LenDummyStrLenLocalB string %%a
    CALL :TimeStamp StrLenLocalEnd

    TITLE B - StrLenNoLocalBrackets
    CALL :TimeStamp StrLenNoLocalBracketsStart
    FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenNoLocalBrackets LenDummyStrLenNoLocalBracketsB string %%a
    CALL :TimeStamp StrLenNoLocalBracketsEnd

    TITLE B - StrLenNoLocal
    CALL :TimeStamp StrLenNoLocalStart
    FOR /L %%a IN (1,1,%Loops%) DO CALL :StrLenNoLocal LenDummyStrLenNoLocalB string %%a
    CALL :TimeStamp StrLenNoLocalEnd

    TITLE Results
    ECHO.

    REM "Empty" Timestamp Measure
    CALL :TimeStamp TimestampStart
    CALL :TimeStamp TimestampEnd
    CALL :MeasureTime TimestampTime TimestampStart TimestampEnd

    ECHO Time StrLenNoLocal          A :  !StrLenNoLocalTime!
    ECHO Time StrLenNoLocalBrackets  A :  !StrLenNoLocalBracketsTime!
    ECHO Time StrLenLocal            A :  !StrLenLocalTime!
    ECHO Time StrLenLocalBrackets    A :  !StrLenLocalBracketsTime!
    ECHO StrLen !LenDummyStrLenNoLocalA! / !LenDummyStrLenNoLocalBracketsA! / !LenDummyStrLenLocalA! / !LenDummyStrLenLocalBracketsA!
    ECHO.

    CALL :MeasureTime StrLenNoLocalTime StrLenNoLocalStart StrLenNoLocalEnd
    CALL :MeasureTime StrLenNoLocalBracketsTime StrLenNoLocalBracketsStart StrLenNoLocalBracketsEnd
    CALL :MeasureTime StrLenLocalTime StrLenLocalStart StrLenLocalEnd
    CALL :MeasureTime StrLenLocalBracketsTime StrLenLocalBracketsStart StrLenLocalBracketsEnd

    ECHO Time StrLenNoLocal          B :  !StrLenNoLocalTime!
    ECHO Time StrLenNoLocalBrackets  B :  !StrLenNoLocalBracketsTime!
    ECHO Time StrLenLocal            B :  !StrLenLocalTime!
    ECHO Time StrLenLocalBrackets    B :  !StrLenLocalBracketsTime!
    ECHO StrLen !LenDummyStrLenNoLocalB! / !LenDummyStrLenNoLocalBracketsB! / !LenDummyStrLenLocalB! / !LenDummyStrLenLocalBracketsB!
    ECHO.
    ECHO "Empty" Timestamp Measure   :  !TimestampTime!
    ECHO Timeout /T 5                :  !TimeoutTime!
    ECHO ping 1.2.3.4 -n 1 -w 5000   :  !PingTime!
    ECHO PingOneHundredTimes         :  !PingOneHundredTimesTime!
    ECHO PingOneHundredTimesBrackets :  !PingOneHundredTimesBracketsTime!
    ECHO.
    EXIT /B
)

输出量:

Time StrLenNoLocal          A :  20.40sec
Time StrLenNoLocalBrackets  A :  16.82sec
Time StrLenLocal            A :  19.84sec
Time StrLenLocalBrackets    A :  19.17sec
StrLen 8191 / 8191 / 8191 / 8191

Time StrLenNoLocal          B :  17.40sec
Time StrLenNoLocalBrackets  B :  14.93sec
Time StrLenLocal            B :  17.64sec
Time StrLenLocalBrackets    B :  18.52sec
StrLen 8191 / 8191 / 8191 / 8191

"Empty" Timestamp Measure   :  0.00sec
Timeout /T 5                :  5.16sec
ping 1.2.3.4 -n 1 -w 5000   :  4.59sec
PingOneHundredTimes         :  50.50sec
PingOneHundredTimesBrackets :  50.50sec

...

Time StrLenNoLocal          A :  18.76sec
Time StrLenNoLocalBrackets  A :  16.76sec
Time StrLenLocal            A :  19.09sec
Time StrLenLocalBrackets    A :  19.67sec
StrLen 8191 / 8191 / 8191 / 8191

Time StrLenNoLocal          B :  18.24sec
Time StrLenNoLocalBrackets  B :  15.97sec
Time StrLenLocal            B :  18.63sec
Time StrLenLocalBrackets    B :  19.60sec
StrLen 8191 / 8191 / 8191 / 8191

"Empty" Timestamp Measure   :  0.00sec
Timeout /T 5                :  4.52sec
ping 1.2.3.4 -n 1 -w 5000   :  4.56sec
PingOneHundredTimes         :  50.49sec
PingOneHundredTimesBrackets :  50.49sec

I'm called ":LabelBrackets" .
I'm called ":LabelInsideLabelBrackets" .

I'm called ":LabelBracketsWOExit" .
I'm called ":LabelBracketsWOExit" .
I'm called ":LabelInsideLabelBracketsWOExit" .

我得出以下结论:

ECHO %time%
timeout /T 5
ECHO %time%
  • 不是5秒。;)
  • 我每次都在“StrLenNoLocalBrackets”中得到最低点。
  • 我还没有发现一个命令链,括号内的任何东西都会导致问题。*
:LongLabel
(
   ECHO I'm called "%~0" , because I have two extra lines.
   EXIT /B
)

*LongLabel仍然是 * 赢家(只要你知道你在做什么)。;)

  • 只是最后的修订**(我想我已经走得太远了):

我还是发现了一个美中不足:

@ECHO OFF

SET "S="
CALL :A

SET "S="
CALL :B

SET "S="
CALL :C

SET "S="
CALL :D

SET "S="
CALL :E

SET "S="
CALL :F

GOTO :EOF

:A
(
   SETLOCAL
   SET S=LOCALC
   ENDLOCAL
   ECHO %~0: %S% --^> Empty
   EXIT /B
)

:B
SETLOCAL
SET S=LOCALC
(
   ENDLOCAL
   ECHO %~0: %S% ^<-- Set
   EXIT /B
)

:C
(
   SETLOCAL
   SET S=LOCALC
   (
      ENDLOCAL
      ECHO %~0: %S% --^> Empty
      EXIT /B
   )
)

:D
(
   SETLOCAL
   SET S=LOCALC
)
(
   ENDLOCAL
   ECHO %~0: %S% ^<-- Set
   EXIT /B
)

:E
(
   SETLOCAL
   SET S=LOCALC
   ENDLOCAL & ECHO %~0: %S% --^> Empty & EXIT /B
)

:F
SETLOCAL
SET S=LOCALC
ENDLOCAL & ECHO %~0: %S% ^<-- Set & EXIT /B

ECHO End of batch (should not be echoed)

注意D、EF之间的区别

:A:  --> Empty
:B: LOCALC <-- Set
:C:  --> Empty
:D: LOCALC <-- Set
:E:  --> Empty
:F: LOCALC <-- Set

这意味着你不能把所有的东西都放在一起,期待同样的结果。

相关问题