我有一个批处理文件:
:extract_stream
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "delims=" %%A IN ('%media_info% "--output=%stream_count_string%" "%file%"') DO SET /A "stream_type_total=%%A"
SET /A "stream_count=1"
FOR /F "tokens=1-4 delims=," %%A IN ('%media_info% "--output=%format_string%" "%file%"') DO (
SET /A "id=%%A-1"
SET "title=%%B"
SET "codec=%%C"
SET "language=%%D"
REM SET "id=!id:~1!"
SET "title=!title:~1!"
SET "codec=!codec:~1!"
SET "language=!language:~1!"
IF NOT DEFINED language SET "language=English"
REM IF "!codec!" EQU "V_MPEG4/ISO/AVC" SET "language="
SET stream_obj[!stream_count!].id=!id!
ECHO ID:!id! Title=!title!, Codec=!codec!, Lamguage=!language!
SET /A "stream_count+=1"
)
( ENDLOCAL
FOR /L %%A IN (1,1,%stream_type_total%) DO (
CALL SET "stream_obj[%%A].id=%stream_obj[%%A].id%"
)
)
GOTO:EOF
但我无法在%%A
循环中FOR /L
按预期工作。
如果我使用1
而不是%%A
这样的数字,那就可以了。
SET "stream_obj[1].id=%stream_obj[1].id%"
但是FOR /L
循环中的命令行无效:
SET "stream_obj[%%A].id=%stream_obj[%%A].id%"
为什么?
当我使用echo
进行核对时,它会在等号=
处切割奇数行。所以我不知道它是否与此有关。
答案 0 :(得分:1)
不要使用算术表达式为环境变量赋值。通常没有理由这样做。只需使用SET "stream_type_total=%%A"
而不使用/A
。
命令GOTO
与其第一个参数:EOF
之间应该有一个空格。
但主要问题是命令块:
( ENDLOCAL
FOR /L %%A IN (1,1,%stream_type_total%) DO (
CALL SET "stream_obj[%%A].id=%stream_obj[%%A].id%"
)
)
命令 ENDLOCAL 不仅会恢复延迟环境变量扩展的先前状态,还会丢弃当前活动的环境变量列表并恢复以前的环境变量列表。有关命令 SETLOCAL 和 ENDLOCAL 的详细信息,请阅读this answer。
因此,在此命令之后,环境变量stream_type_total
以及所有stream_obj[x].id
环境变量不再存在。
我建议将此命令块修改为:
FOR /L %%A IN (1,1,%stream_type_total%) DO CALL SET "stream_obj[%%A].id=%stream_obj[%%A].id%"
ENDLOCAL
现在 FOR 循环应该按预期工作。
但请注意,即使进行此更改,修改后的stream_obj[x].id
环境变量在命令 ENDLOCAL 后也不再存在。
最好避免在此子例程中使用 SETLOCAL 和 ENDLOCAL ,就像使用此代码一样:
:extract_stream
FOR /F "delims=" %%A IN ('%media_info% "--output=%stream_count_string%" "%file%"') DO SET "stream_type_total=%%A"
SET "stream_count=1"
FOR /F "tokens=1-4 delims=," %%A IN ('%media_info% "--output=%format_string%" "%file%"') DO (
SET /A "id=%%A-1"
SET "title=%%B"
SET "codec=%%C"
SET "language=%%D"
REM SET "id=!id:~1!"
CALL SET "title=%%title:~1%%"
CALL SET "codec=%%codec:~1%%"
IF DEFINED language CALL SET "language=%%language:~1%%"
IF NOT DEFINED language SET "language=English"
REM IF "!codec!" EQU "V_MPEG4/ISO/AVC" SET "language="
CALL SET "stream_obj[%%stream_count%%].id=%%id%%"
CALL ECHO ID:%%id%% Title=%%title%%, Codec=%%codec%%, Language=%%language%%
SET /A "stream_count+=1"
)
FOR /L %%A IN (1,1,%stream_type_total%) DO CALL SET "stream_obj[%%A].id=%stream_obj[%%A].id%"
GOTO :EOF
使用命令 REM 注释掉的命令在上面的代码中被 修改。
另一种解决方案是再使用一个子程序:
:extract_stream
FOR /F "delims=" %%A IN ('%media_info% "--output=%stream_count_string%" "%file%"') DO SET "stream_type_total=%%A"
SET "stream_count=1"
FOR /F "tokens=1-4 delims=," %%A IN ('%media_info% "--output=%format_string%" "%file%"') DO CALL :UpdateVariables "%%~A" "%%~B" "%%~C" "%%~D"
FOR /L %%A IN (1,1,%stream_type_total%) DO CALL SET "stream_obj[%%A].id=%stream_obj[%%A].id%"
GOTO :EOF
:UpdateVariables
SET /A "id=%~1-1"
SET "title=%~2"
SET "codec=%~3"
SET "language=%~4"
REM SET "id=%id:~1%"
SET "title=%title:~1%"
SET "codec=%codec:~1%"
IF DEFINED language SET "language=%language:~1%"
IF NOT DEFINED language SET "language=English"
REM IF "%codec%" == "V_MPEG4/ISO/AVC" SET "language="
SET "stream_obj[%stream_count%].id=%id%"
ECHO ID:%id% Title=%title%, Codec=%codec%, Language=%language%
SET /A "stream_count+=1"
GOTO :EOF
使用命令 REM 注释掉的命令也会在上面的代码中修改。
最后一个提示:在比较字符串时不要使用比较运算符EQU
。此运算符用于比较32位有符号整数值,而不是用于字符串比较。请阅读Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files上的答案,了解有关使用命令 IF 比较字符串或整数值的详细信息。
答案 1 :(得分:0)
如果您尝试从setlocal范围中获取多个值,则无法以您尝试的方式使用循环/调用。
我看到两种不同的解决方案 1)通过离开setlocal范围并重新输入,在每个循环中挽救一个值。 但是你也失去了所有其他变量,比如stream_count
2)使用带有一个聚合变量的endlocal
块来减少所有变量。
喜欢
设置“rescue =%stream_obj [1] .id%:%stream_obj [2] .id%:%stream_obj [3] .id%”
另见
exit function and preserve variable over endlocal barrier
Macro to return multiple variables across endlocal barriers