变量的行为不符合预期

时间:2015-05-17 02:35:49

标签: batch-file delayedvariableexpansion

我一直在努力尝试在这个批处理文件中使用语法,但我无法弄清楚为什么有些东西不起作用。

  1. 每次执行变量i时都不会增加。
  2. strc上的连接似乎没有连接。
  3. 这是我的代码:

    set i=0
    set "strc=concat:"
    
    for %%f in (*.mp4) do (
        set /a i+=1
        set "str=intermediate%i%.ts"
    
        set strc="%strc% %str%|"
    
        ffmpeg -i "%%f" -c copy -bsf:v h264_mp4toannexb -f mpegts "%str%"
    )
    
    set strc="%strc:-1%"
    ffmpeg -i "%strc%" -c copy -bsf:a aac_adtstoasc Output.mp4
    

1 个答案:

答案 0 :(得分:34)

你不是第一个陷入着名的延迟陷阱陷阱的人。 (并且你不会成为最后一个)。

如果要使用在同一块中更改的变量(块是括号()中的一系列命令),则需要延迟扩展。

延迟变量引用!var!而不是%var%

原因是cmd解析代码的方式。一次解析完整的行或块,用解析时的值替换普通变量。延迟变量在运行时进行评估。

两个简单的批处理文件来演示:

setlocal EnableDelayedExpansion
set "var=hello"
if 1==1 (
    set "var=world"
    echo %var% !var!
)
setlocal EnableDelayedExpansion
for /L %%i in (1,1,5) do (
    echo %random% !random!
)

注意:一条线也被视为一个块:

set "var=old"
set "var=new" & echo %var% 

延迟扩张:

setlocal EnableDelayedExpansion
set "var=old"
set "var=new" & echo !var! 

默认情况下,在命令提示符下关闭延迟扩展。如果你确实需要它,你可以这样做:

cmd /V:ON /C "set "var=hello" & echo !var!"

还有一种方法可以在没有延迟扩展的情况下做同样的事情(但是call需要花费一些时间,因此速度较慢,但​​如果由于某种原因你不能延迟扩展。我想使用延迟扩展,它是另一种选择):

setlocal DISabledelayedexpansion
for /L %%i in (1 1 5) do (
    call echo %random% %%random%% 
)

这两种方法也可用于显示array-like variables

(这经常被问到"变量包含另一个变量"或"嵌套变量")

以下是在不同情况下使用此类数组变量的集合:

延迟扩展:

setlocal ENableDelayedExpansion
set "num=4"
set "var[%num%]=HELLO"
echo plain delayed: !var[%num%]!
for /L %%i in (4 1 4) do (
    echo for delayed: !var[%%i]!
    set a=%%i
    call echo for delayed with variable: %%var[!a!]%%
)

没有延迟扩展:

setlocal DISableDelayedExpansion
set "num=4"
set "var[%num%]=HELLO"
call echo plain called: %%var[%num%]%%
for /L %%i in (4 1 4) do (
    call echo FOR called: %%var[%%i]%%
    set a=%%i
    call echo FOR called with variable: %%var[%a%]%%
)

注意setlocal在批量文件之外无效,因此delayedexpansion仅适用于:
- 批处理文件中 - 启用延迟展开时启动cmd(cmd /V:ON)(默认情况下,cmd以延迟展开 dis 启用)