Windows批处理-提取值以进行ffmpeg处理

如何解决Windows批处理-提取值以进行ffmpeg处理

我有几十个json文件,我试图在每个文件中找到两个值,并将结果分配给两个单独的变量,以进行ffmpeg处理。

一个示例json文件如下所示:

{
    "year": "2018","track": "12",... other data omitted
}

我希望提取2018和12,以便可以在以下ffmpeg命令中使用它们:

ffmpeg -i "same_file_name_as_json.m4a" -Metadata:s:a:0 year=2018 --Metadata:s:a:0 track=12 -acodec libmp3lame "same_file_name_as_json.mp3"

是否可以编写单个批处理文件来获得所需的结果?任何帮助将不胜感激,因为我是findstr和设置变量的新手。谢谢。

已编辑:

set "year=" & set "track="
for %%i in (*.json) do (
  for /f "usebackq tokens=1,2 delims={:}," %%a in ("%%i") do (
    set "%%~a=%%~b"
    if defined year if defined track goto :CONT
    )
:CONT
C:\ffmpeg -i "%%~ni.m4a" -Metadata:s:a:0 year=%year% -Metadata:s:a:0 track=%track% -acodec libmp3lame "%%~ni.mp3"
)
pause

解决方法

Windows批处理脚本不了解JSON文件格式,因此最好使用本机支持的语言。将JSON视为“普通”文本不是最好的主意,因为只有一点不违反JSON格式的更改(例如,添加,删除或移动的换行符)仍然会造成很大的麻烦。>

也就是说,假设JSON文件完全按照您显示的样子显示,并且具有Unix或DOS / Windows风格的换行符(即回车符和换行符),该代码可以为您工作:

for /F "usebackq tokens=1,2 delims={:}," %%M in ("file.json") do set "%%~M=%%~N"
echo year  = %year%
echo track = %track%

如果您有一个巨大的JSON文件,不想不必要地进行完全处理,则可以改用以下代码:

set "year=" & set "track="
for /F "usebackq tokens=1," %%M in ("file.json") do (
    set "%%~M=%%~N"
    if defined year if defined track goto :CONT
)
:CONT
echo year  = %year%
echo track = %track%

如果要提取的(非数组)值也可能包含定义的定界符之一({:}, SPACE ),您可以将代码扩展为此,因为值不包含字符*?<>

set "year=" & set "track="
for /F "usebackq tokens=1,* delims={:}," %%M in ("file.json") do (
    for %%K in (%%N) do set "%%~M=%%~K"
    if defined year if defined track goto :CONT
)
:CONT
echo year  = %year%
echo track = %track%

要防止脚本分配不必要的多余变量,您可以尝试以下操作:

for /F "usebackq tokens=1," %%M in ("file.json") do (
    if "%%~M"=="year" (set "%%~M=%%~N") else if "%%~M"=="track" set "%%~M=%%~N"
)
echo year  = %year%
echo track = %track%

或者通过findstr命令预先识别数据并过滤出所需的行:

for /F "tokens=1," %%M in ('
    findstr /R /C:"^ *\"year\" *:" /C:"^ *\"track\" *:" "file.json"
') do set "%%~M=%%~N"
echo year  = %year%
echo track = %track%

基于您的edit,让我建议使用上述方法中的最后一种,因为没有goto :CONT,因为它会破坏块上下文,因此无法在循环中使用,并且确实不分配其他不需要的变量。由于变量是在循环体内写入读取的,因此您必须启用并应用delayed variable expansion。我将通过以下方式进行所有操作:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem /* Iterate over the `*.json` files in the current working directory (`%CD%`);
rem    to use the parent directory of this script,use `%~dp0*.json` instead: */
for %%I in ("*.json") do (
    rem // Store name of current JSON file in variable:
    set "name=%%~nI"
    rem // Clear variables for later check for availability:
    set "year=" & set "track="
    rem // Process the current JSON file:
    for /F "tokens=1," %%M in ('
        findstr /R /C:"^ *\"year\" *:" /C:"^ *\"track\" *:" "%%~I"
    ') do (
        rem // Assign year and track variables:
        set "%%~M=%%~N"
        rem // Check of both year and track are available:
        if defined year if defined track (
            rem // Toggle delayed expansion to avoid troubles with `!`:
            setlocal EnableDelayedExpansion
            rem // Eventually execute `ffmpeg` tool using all the derived data:
            ffmpeg -i "!name!.m4a" -metadata:s:a:0 year=!year! -metadata:s:a:0 track=!track! -acodec libmp3lame "!name!.mp3"
            endlocal
        )
    )
)
endlocal
exit /B
,

我有几十个json文件...

Windows的cmd不支持JSON,因此您必须诉诸PowerShell或使用支持此功能的外部工具。您可能会发现有趣。

要提取“年份”和“曲目”的值:

xidel -s input.json -e "$json/(year,track)"
#or
xidel -s input.json -e "$json/year,$json/track"
2018
12

要导出到变量%year%%track%

FOR /F "delims=" %A IN ('xidel -s input.json -e "$json/(year:=year,track:=track)" --output-format^=cmd') DO %A
#or
FOR /F "delims=" %A IN ('xidel -s input.json -e "year:=$json/year,track:=$json/track" --output-format^=cmd') DO %A

但是,您不需要变量来创建所需的字符串(ffmpeg命令)。 xidel也可以做到这一点。

您可以使用FOR循环遍历所有JSON文件...

FOR %A IN (*.json) DO @xidel -s %A -e "$json/concat('ffmpeg -i \"%~nA.m4a\" -metadata:s:a:0 year=',year,' --metadata:s:a:0 track=',track,' -acodec libmp3lame \"%~nA.mp3\"')"
ffmpeg -i "name-of-json-file.m4a" -metadata:s:a:0 year=2018 --metadata:s:a:0 track=12 -acodec libmp3lame "name-of-json-file.mp3"

...但是为每个JSON文件调用xidel效率很低。 xidel可以更有效地做到这一点。
xidelFOR %A IN (*.json) DO @ECHO %A等效为xidel -se "file:list(.,false(),'*.json')"

然后,您可以使用以下查询一次处理所有JSON文件:

xidel -se "for $x in file:list(.,'*.json') return json-doc($x)/concat('ffmpeg -i \"',replace($x,'json','m4a'),'\" -metadata:s:a:0 year=',' -acodec libmp3lame \"','mp3'),'\"')"

预设的命令/查询:

xidel -se ^"^
  for $x in file:list(.,'*.json') return^
  json-doc($x)/concat(^
    'ffmpeg -i \^"',^
    replace($x,^
    '\^" -metadata:s:a:0 year=',^
    year,^
    ' --metadata:s:a:0 track=',^
    track,^
    ' -acodec libmp3lame \^"',^
    '\^"'^
  )^
"

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?