Las variables no se comportan como se esperaba.

Resuelto Eric Marcinowski asked hace 9 años • 1 respuestas

He estado luchando para lograr la sintaxis correcta en este archivo por lotes y no puedo entender por qué algunas cosas no funcionan.

  1. La variable ino aumenta cada vez que lo hago.
  2. La concatenación strcno parece concatenarse.

Aquí está mi código:

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
Eric Marcinowski avatar May 17 '15 09:05 Eric Marcinowski
Aceptado

No eres el primero que cae en la famosa "trampa de la expansión retrasada" (y no serás el último).

Necesita una expansión retrasada si desea utilizar una variable que cambió en el mismo bloque (un bloque es una serie de comandos entre paréntesis (y )).

Se hace referencia a las variables retrasadas con !var!en lugar de %var%.

La razón es el camino, cmdanaliza el código. Una línea o bloque completo se analiza a la vez, reemplazando las variables normales con su valor en el momento del análisis. Las variables retrasadas se evalúan en tiempo de ejecución.

Dos archivos por lotes simples para demostrar:

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

Nota : Una línea también se trata como un bloque:

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

Con expansión retrasada:

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

La expansión retrasada está desactivada de forma predeterminada en el símbolo del sistema. Si realmente lo necesitas, puedes hacer:

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

También hay una manera de hacer lo mismo sin expansión retrasada (pero callcuesta algo de tiempo, por lo que es más lento, pero si por alguna razón no puedes o no quieres usar la expansión retrasada, es una alternativa):

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

Ambos métodos también se pueden utilizar para mostrar variables tipo matriz :

(Esto a menudo se pregunta como "variable que contiene otra variable" o "variables anidadas")

Aquí hay una colección para usar variables similares a matrices en diferentes situaciones:

Con expansión retrasada:

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

sin expansión retrasada:

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

Nota : setlocalno tiene ningún efecto fuera de los archivos por lotes, por lo que delayedexpansionsolo funciona:

  • En archivos por lotes
  • Cuando el cmd se inició con la expansión retardada habilitada ( cmd /V:ON) (de forma predeterminada, el cmd se ejecuta con la expansión retardada deshabilitada )

(Siga los enlaces cuando esté interesado en conocimientos técnicos o incluso en aspectos técnicos avanzados )

Stephan avatar May 17 '2015 06:05 Stephan