变量的行为不符合预期

32

我一直在苦苦寻找正确的批处理文件语法,但我无法弄清楚为什么有些事情不起作用。

  1. 每次执行时变量i都没有被递增。
  2. strc的连接似乎没有起作用。

这是我的代码:

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
可能是如何在循环for /F中设置变量的重复问题。 - melpomene
1个回答

62

你不是第一个陷入著名的“延迟扩展陷阱”的人(你也不会是最后一个)。

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

延迟变量使用!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%% 
)

两种方法也可以用来显示类似数组的变量:

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

下面是在不同情况下使用这种类似数组的变量的集合:

使用延迟扩展:

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 运行时延迟扩展被禁用)
(如果您对 技术背景 或甚至高级技术内容 感兴趣,请点击链接)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接