Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
149 views
in Technique[技术] by (71.8m points)

windows - Variables are not behaving as expected

I've been wrestling trying to get the syntax right on this batch file and I cannot figure out why some things aren't working.

  1. The variable i is not getting incremented each time I do it.
  2. Concatenation on strc doesn't seem to concatenate.

Here is my code:

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
question from:https://stackoverflow.com/questions/65926974/batch-how-to-combine-two-variables-into-one

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You are not the first, who fell into the famous "delayed expansion trap" (and you won't be the last).

You need delayed expansion if you want to use a variable, that you changed in the same block (a block is a series of commands within brackets (and )).

Delayed variables are referenced with !var! instead of %var%.

Reason is the way, cmd parses the code. A complete line or block is parsed at once, replacing normal variables with their value at parse time. Delayed variables are evaluated at runtime.

Two simple batch files to demonstrate:

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!
)

Note: A line is also treated as a block:

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

With delayed expansion:

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

Delayed expansion is per default turned off at the command prompt. If you really need it, you can do:

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

Also there is a way to do the same without delayed expansion (but call costs some time, so it's slower, but if for some reason you can't / don't want to use delayed expansion, it's an alternative):

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

Both methods can also be used to display array-like variables:

(This is often asked like "variable which contains another variable" or "nested variables")

Here is a collection for using such array-like variables in different situations:

With delayed expansion:

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!]%%
)

without delayed expansion:

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%]%%
)

Note: setlocal has no effect outside of batchfiles, so delayedexpansion works only:

  • In batch files
  • When the cmd was started with delayed expansion enabled (cmd /V:ON) (by default, the cmd runs with delayed expansion disabled)

(Follow the links, when you are interested in the technical background or even the advanced technical stuff)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...