从 "complicated" JSON 文件中读取一个值

Read a value out of a "complicated" JSON file

我正在使用 jq,但我没能在批处理脚本中从 .json 文件(我由 mediainfo 生成)中提取值。

如何获取变量中“Duration”的值以供进一步使用?

{
"creatingLibrary": {
"name": "MediaInfoLib",
"version": "21.09",
"url": "https://mediaarea.net/MediaInfo"
},
"media": {
"@ref": "J:\Austria\Tag5\EOS_ben\100EOS5D\TW_6248.MOV",
"track": [
{
"@type": "General",
"VideoCount": "1",
"AudioCount": "1",
"OtherCount": "1",
"FileExtension": "MOV",
"Format": "MPEG-4",
"Format_Profile": "QuickTime",
"CodecID": "qt  ",
"CodecID_Version": "2007.09",
"CodecID_Compatible": "qt  /CAEP",
"FileSize": "37229924",
"Duration": "9.520",
"OverallBitRate_Mode": "VBR",
"OverallBitRate": "31285650",
"FrameRate": "25.000",
"FrameCount": "238",
"StreamSize": "100484",
"HeaderSize": "98304",
"DataSize": "37130652",
"FooterSize": "968",
"IsStreamable": "Yes",
"Encoded_Date": "UTC 2014-03-13 22:31:17",
"Tagged_Date": "UTC 2014-03-13 22:31:17",
"File_Created_Date": "UTC 2014-03-13 21:31:26.000",
"File_Created_Date_Local": "2014-03-13 23:31:26.000",
"File_Modified_Date": "UTC 2014-03-13 21:31:26.000",
"File_Modified_Date_Local": "2014-03-13 23:31:26.000",
"Copyright": "BEN PAYA",
"extra": {
"com_apple_quicktime_make": "Canon",
"com_apple_quicktime_model": "Canon EOS 5D Mark III",
"com_apple_quicktime_rating_user": "0.000",
"com_apple_quicktime_author": "PhilFried"
}
},
{
"@type": "Video",
"StreamOrder": "0",
"ID": "1",
.
.
.

那就是

your_json_file.media.track[0].Duration

其中.track[index]表示某个元素(轨道),在本例中是第一个。


您应该尝试在线 JSON 格式化程序,例如 JSON Formatter & Validator,以获得自动缩进。

这是您缩进的文件内容:

{
   "creatingLibrary":{
      "name":"MediaInfoLib",
      "version":"21.09",
      "url":"https://mediaarea.net/MediaInfo"
   },
   "media":{
      "@ref":"J:\Austria\Tag5\EOS_ben\100EOS5D\TW_6248.MOV",
      "track":[
         {
            "@type":"General",
            "VideoCount":"1",
            "AudioCount":"1",
            "OtherCount":"1",
            "FileExtension":"MOV",
            "Format":"MPEG-4",
            "Format_Profile":"QuickTime",
            "CodecID":"qt  ",
            "CodecID_Version":"2007.09",
            "CodecID_Compatible":"qt  /CAEP",
            "FileSize":"37229924",
            "Duration":"9.520",
            "OverallBitRate_Mode":"VBR",
            "OverallBitRate":"31285650",
            "FrameRate":"25.000",
            "FrameCount":"238",
            "StreamSize":"100484",
            "HeaderSize":"98304",
            "DataSize":"37130652",
            "FooterSize":"968",
            "IsStreamable":"Yes",
            "Encoded_Date":"UTC 2014-03-13 22:31:17",
            "Tagged_Date":"UTC 2014-03-13 22:31:17",
            "File_Created_Date":"UTC 2014-03-13 21:31:26.000",
            "File_Created_Date_Local":"2014-03-13 23:31:26.000",
            "File_Modified_Date":"UTC 2014-03-13 21:31:26.000",
            "File_Modified_Date_Local":"2014-03-13 23:31:26.000",
            "Copyright":"BEN PAYA",
            "extra":{
               "com_apple_quicktime_make":"Canon",
               "com_apple_quicktime_model":"Canon EOS 5D Mark III",
               "com_apple_quicktime_rating_user":"0.000",
               "com_apple_quicktime_author":"PhilFried"
            }
         }
      ]
   }
}
@ECHO OFF
SETLOCAL

rem The following settings for the source directory & filename are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.

SET "sourcedir=u:\your files"
SET "filename1=%sourcedir%\q71716898.txt"

REM (
FOR /f "usebackqtokens=1,2delims=:, " %%b IN ("%filename1%") DO (
 IF /i "%%~b"=="duration" SET "duration=%%~c"
)
SET duration
GOTO :EOF

相当标准的 for /f "tokens 处理。

for/f 依次分配每行的标记,标记 1 到 %%b,标记 2 到 %%c

选择 :,space 分隔符,目标行的第一个标记是 "Duration" 和第二个 "9.520".

因此,检查“%%~b”(标记,去掉引号,然后引号中的 re-enclosed 与引号中的字符串 duration 相同),如果是,将第二个token的值赋值给变量duration.

如果令牌包含会干扰 if 解析的分隔符,则需要 dequote/enquote 仪式,并且 /i 进行比较 case-insensitive。

最好使用能理解JSON语言的工具。这将 运行 在 batch-file 来自 cmd.

我注意到 track 是一个数组。此代码选择数组的第一个元素。

FOR /F "delims=" %%A IN ('powershell.exe -NoLogo -NoProfile -Command ^
    "(ConvertFrom-Json -InputObject (Get-Content -Path '.\dura.json' -Raw)).media.track[0].Duration"') DO (SET "DURATION=%%~A")
ECHO DURATION is %DURATION%

如果您想处理所有轨道的 Duration,请尝试一些代码并根据需要创建一个新问题。

{} 用于散列 table。使用[]表示和array.

要在 JSON 内容中获得 FrameCount,我的解决方案是:

jq.exe -r .media.track[0].FrameCount C:\MP4convert\test\%filenam%.json > test1.txt
for /f "delims=" %%x in (test1.txt) do set FrCountVar=%%x

为了将来使用,我将计数放在一个新变量中:

SET FrCount=%FrCountVar%

谢谢

您可以通过纯批处理文件以非常简单的方式解决您的问题:

@echo off
setlocal

for /F "tokens=2 delims=:, " %%a in ('findstr "Duration" test.txt') do set "Duration=%%~a"

echo Duration = %Duration%

另外,同样的方法可以得到所有字段的值:

@echo off
setlocal

for /F "tokens=1,2 delims=:, " %%a in ('findstr /V "{ [ ] }" test.txt') do set "%%~a=%%~b"

rem Here you have the values of *all fields* in the json file. For example:

echo Duration = %Duration%
echo FrameCount = %FrameCount%
echo CodecID_Version = %CodecID_Version%

输出:

Duration = 9.520
FrameCount = 238
CodecID_Version = 2007.09