批处理文件中延迟扩展的示例

时间:2012-05-11 20:39:27

标签: batch-file cmd delayedvariableexpansion

有人可以给我一个例子,说明批处理脚本在有或没有延迟扩展的情况下会有不同的行为吗?您是否有任何不希望使用延迟扩展的情况?感谢。

3 个答案:

答案 0 :(得分:52)

请看下面的例子......

示例1:以下代码不使用延迟扩展,因此for循环中的变量只展开一次。这意味着无论我们使用set命令对它做什么,%Count%将在循环的每次迭代中始终扩展为0

@echo off
set COUNT=0

for %%v in (1 2 3 4) do (
  set /A COUNT=%COUNT% + 1
  echo Count = %COUNT%
)
pause

所以这个脚本将输出:

Count = 0
Count = 0
Count = 0
Count = 0

这不是这个循环应该如何工作的。

示例2:另一方面,如果我们使用延迟扩展,我们将使用以下脚本,该脚本将按预期运行。

setlocal ENABLEDELAYEDEXPANSION
set COUNT=0

for %%v in (1 2 3 4) do (
  set /A COUNT=!COUNT! + 1
  echo Count = !COUNT!
)

pause

并且,正如预期的那样,它将输出:

Count = 1
Count = 2
Count = 3
Count = 4

当您使用ENABLEDELAYEDEXPANSION并使用!而不是%展开变量时,每次都会重新展开变量,并且所有内容都按预期工作。

答案 1 :(得分:8)

Max's answer提供了一个示例,说明批处理脚本在有或没有延迟扩展的情况下会采取不同的行为

为了完整起见,让我们回答问题的另一部分,并在您的数据包含感叹号时显示您不希望使用延迟展开的情况 {{1 (并显示处理此类数据的两种方法):

!

请注意,上面的脚本显示proper ways of escaping

  • @ECHO OFF SETLOCAL EnableExtensions DisableDelayedExpansion set "_auxFile=%temp%\%~n0.txt" rem create multiline sample file >"%_auxFile%" ( for /L %%G in (1,1,3) do echo line %%G is 100%% valid! Sure! Hurrah!) rem create one-line sample file >"%_auxFile%" echo this line is 100%% valid! Sure! Hurrah! echo( echo --- file content type "%_auxFile%" echo( SETLOCAL EnableDelayedExpansion echo --- enabled delayed expansion chokes down unescaped exclamation marks^^^! "^!" for /F "usebackq delims=" %%G in ("%_auxFile%") do ( set "_auxLine=%%~G" echo loop var=%%~G echo _auxLine=!_auxLine! ) ENDLOCAL echo( SETLOCAL DisableDelayedExpansion echo --- toggled delayed expansion works although might be laborious! for /F "usebackq delims=" %%G in ("%_auxFile%") do ( set "_auxLine=%%G" echo loop var=%%G SETLOCAL EnableDelayedExpansion echo _auxLine=!_auxLine! ENDLOCAL ) ENDLOCAL echo( SETLOCAL DisableDelayedExpansion echo --- keep delayed expansion DISABLED: use CALL command! for /F "usebackq delims=" %%G in ("%_auxFile%") do ( set "_auxLine=%%G" echo loop var=%%G call :ProcessVar ) ENDLOCAL rem delete the sample file del "%_auxFile%" ENDLOCAL goto :eof :ProcessVar echo _auxLine=%_auxLine% echo WARNING: neither !_auxLine! nor %%G loop variable is available here! goto :eof 百分号%加倍(延迟扩展无关紧要),
  • 如果启用了延迟扩展,则为
  • %%感叹号:
    • !如果用一对双引号括起来,请使用"^!"和批处理脚本常规转义字符cmd插入符号;
    • ^否则,请使用三个^^^!插页符号。

<强>输出

^

答案 2 :(得分:0)

正如答案中所指出的,延迟扩展的主要用途是在括号上下文中设置和访问变量。

虽然它在其他情况下也很有用。

参数化子字符串和字符串替换:

@echo off
setlocal enableDelayedExpansion

set "string=test string value"
set start=5
set get_next=6

echo #!string:~%start%,%get_next%!#

set "search_for=string"
set "replace_with=text"

echo #!string:%search_for%=%replace_with%!#

输出将是:

#string#
#test text value#

虽然这可以通过额外的调用来实现,但这种方式的性能更高

使用括号内的 shift 命令参数化参数访问

@echo off

echo first attempt:
(
    echo "%~1"
    shift
    echo "%~1"
)
::now the shift command will take effect

setlocal enableDelayedExpansion
echo second attempt:

(   
    set /a argument=1
    call echo %%!argument! 
    shift
    call echo %%!argument! 
)

输出将是:

first attempt:
"first argument"
"first argument"
second attempt:
"second argument"
"third argument"

如您所见,参数化参数访问只能通过延迟扩展来完成。

使用令牌(或函数参数)进行参数化

另一种混合 !% 的方法,这可能对嵌套循环有用:

@echo off
setlocal enabledelayedexpansion
set begin=2
set end=2
set string=12345

for /f "tokens=1,2" %%A in ("!begin! !end!") do set "string2=!string:~%%A,%%B!"
echo !string2!

endlocal

正如您现在看到的,for 命令标记用作参数。