我正尝试使用MKV
脚本中的mkvinfo
从bash
文件中提取曲目信息。输出是一系列长行,具有重复模式作为各种轨道类型的各种轨道属性的分隔符。轨道的一个例子是:
…
| + A track
| + Track number: 6 (track ID for mkvmerge & mkvextract: 5)
| + Track UID: 11555278830806058806
| + Track type: subtitles
| + (Unknown element: TrickTrackFlag; ID: 0xc6 size: 3)
| + Enabled: 1
| + Default flag: 0
| + Forced flag: 0
| + Lacing flag: 0
| + MinCache: 0
| + Timecode scale: 1
| + Name: Spanish
| + Language: spa
| + Codec ID: S_TEXT/UTF8
| + (Unknown element: TrackAttachmentLink; ID: 0x7446 size: 11)
| + Codec decode all: 1
| + A track
| + Track number: 7 (track ID for mkvmerge & mkvextract: 6)
…
可以有给定轨道类型的多个实例,并且轨道的行数有些变化。我需要从特定的轨道类型中提取某些轨道属性。例如,如果我想查找subtitles
跟踪类型的所有实例并提取Track number
和Codec ID
,我可以通过grep管道输出结果:
mkvinfo "file.mkv" | grep "subtitles" -B 2 | grep "Track number"
这将输出包含所有字幕轨道的轨道号的行。我必须将这些行放入一个数组并过滤它们以得到第一个数字,这样我就可以将它与mkvpropedit
一起使用,这需要第一个数字。
类似地:
mkvinfo "file.mkv" | grep "subtitles" -A 10 | grep "Codec ID: " | sed 's/^.**: //'
输出所有字幕轨道的编解码器ID。
这很好 IF 我确切地知道在包含subtitles
的行之前/之后有多少行。问题是,要包含的确切行数因文件而异。所以我需要做的是在| + A track
和以|+
OR | +
OR EOF
开头的行之间输出整行。我还需要过滤块以提取第一个Track number
和Codec ID
。我尝试使用| grep -Eo [0-9]+ | head -1
来提取每首曲目的第一个数字,但它只适用于找到的第一首曲目并退出。如果有一种方法可以让它适用于一行中的所有曲目,那将会很有帮助。我使用sed
给出的第二个示例适用于Codec ID
。
底线问题是:
如何提取特定跟踪类型的特定属性 ,例如给出的示例,并将它们放入一个或多个数组中以便进一步处理?
我希望能够满足以下条件:
bash
(GNU bash,版本4.3.30(1)-release(x86_64-apple-darwin12.5.0))实用程序,如sed
,awk
, grep
,... mkvinfo
的输出到各种实用程序中我发现很多帖子都显示了如何使用sed
在两个单词之间找到一个文本块但是我无法使用整行< / strong>或包含空格的字符串。也许有一种方法可以做到这一点,但我不太了解sed
能够使代码适应我的情况。
请详细说明您的代码如何运作,以便我可以“学习如何钓鱼”。所以下次我可以自己做。
答案 0 :(得分:2)
当以复杂的方式处理多行时,我选择的工具是awk
。
在每个匹配模式中,我们将匹配保存在变量中。
最后,当我们遇到指示新块(| + A track
)的字符串,或者我们到达流的末尾时,我们打印我们感兴趣的变量的值(轨道号,编解码器ID),但仅限于类型是字幕。
mkvinfo ... | gawk '
match($0, /Track number: ([0-9]+)/, m) {TN=m[1]}
match($0, /Codec ID: (.*)$/, m) {CI=m[1]}
/Track type: subtitles/ {SUB=1}
/^\| \+ A track$/ {if(SUB) print TN, CI; unset SUB}
END {if(SUB) print TN, CI; unset SUB}'
您需要gawk
来使用匹配功能来捕获带括号的组。