我经常在:LABEL
中看到括号( ... )
的示意图。
我读了圆括号/方括号,但我不太明白如何在子例程中解释这一点。
(例如https://ss64.com/nt/syntax-brackets.html)
使用括号内的变量
- CMD shell将扩展[读入内存]代码块开头的所有变量,并使用这些值,即使变量的值在代码块中发生了更改。打开DelayedExpansion将强制shell在每行的开头读取变量。*
不幸的是,我在互联网上找不到对调用或子例程的具体描述。
(例如https://ss64.com/nt/call.html、https://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
( ... )
版本比较快。
只要大家没有异议,我的结论是:
我更喜欢行数少的代码,只要它不影响可读性。* 但是 * 如果这两个括号可以使脚本更快一点,而且不会造成任何伤害-为什么不呢?;)
1条答案
按热度按时间rsl1atfo1#
在“如果”之后...
思考:
输出量:
我得出以下结论:
*LongLabel仍然是 * 赢家(只要你知道你在做什么)。;)
我还是发现了一个美中不足:
注意D、E和F之间的区别
这意味着你不能把所有的东西都放在一起,期待同样的结果。