将文本文件读入数组,提取元素并对其进行排序需要很长时间。
文本文件是用于R128音频分析的ffmpeg控制台输出。我需要获得最高的M和S值。示例:
Promises
根据被分析的音频文件的持续时间,文本文件可能长达数百或数千行 我想找到最高的M(-22.2)和S值(-28.6)并将它们分配给变量M和S
这就是我目前使用的:
[Parsed_ebur128_0 @ 0x7fd32a60caa0] t: 4.49998 M: -22.2 S: -29.9 I: -27.0 LUFS LRA: 9.8 LU FTPK: -12.4 dBFS TPK: -9.7 dBFS
[Parsed_ebur128_0 @ 0x7fd32a60caa0] t: 4.69998 M: -22.5 S: -28.6 I: -25.9 LUFS LRA: 11.3 LU FTPK: -12.7 dBFS TPK: -9.7 dBFS
有更快的方法吗?
答案 0 :(得分:2)
不是在内存中读取整个文件,而是将其写入单独的文件,然后再读取它们,只需解析它并选出最大的值:
$ awk '$7 > m || m == "" { m = $7 } $9 > s || s == "" { s = $9 } END { print m, s }' data
-22.2 -28.6
在您的数据中,字段7和9包含M和S的值。awk
脚本将更新其m
和s
变量,如果它们在这些字段中找到更大的值并且然后打印最后找到的最大值。如果尚未读取值,则需要m == ""
和s == ""
来触发值的初始化。
awk
的另一种方式,可能看起来更干净:
$ awk 'FNR == 1 { m = $7; s = $9; next } $7 > m { m = $7 } $9 > s { s = $9 } END { print m, s }' data
将它们分配给shell中的M
和S
:
$ declare $( awk 'FNR == 1 { m = $7; s = $9; next } $7 > m { m = $7 } $9 > s { s = $9 } END { printf("M=%f S=%f\n", m, s) }' data )
$ echo $M $S
-22.200000 -28.600000
如果您想要原始字符串而不是浮点值,请调整printf()
格式以使用%s
而不是%f
,或者设置您可能需要的小数位数,例如{ {1}}取代%.2f
。
答案 1 :(得分:1)
首先,对于单个值提取,三进程管道有点多余,特别是考虑到您为每个行重新重新实例化。
接下来,将所有值保存到文件中,然后对该文件进行排序,而您只需要最大值。您可以在第一个(值提取)循环中轻松找到它,以获得额外的%f
运行时间,而不是I / O和所有I / O开销和O(N)
排序费用的排序。请参阅bash手册中的O(NlogN)
和条件表达式。