[英]Extracting floats from lines with irregular surrounding text
我有一个包含以下内容的文本文件:
[silencedetect @ 0x7fa73cd000c0] silence_start: 1.32515
[silencedetect @ 0x7fa73cd000c0] silence_end: 1.88188 | silence_duration: 0.556735
[silencedetect @ 0x7fa73cd000c0] silence_start: 2.99698
[silencedetect @ 0x7fa73cd000c0] silence_end: 3.42311 | silence_duration: 0.426122
[silencedetect @ 0x7fa73cd000c0] silence_start: 5.58311
[silencedetect @ 0x7fa73cd000c0] silence_end: 6.13984 | silence_duration: 0.556735
[silencedetect @ 0x7fa73cd000c0] silence_start: 7.6729
size=N/A time=00:00:09.12 bitrate=N/A speed= 675x
并且我想提取“ silence_start:”和“ silence_end:”位之后的值(即值1.32515、1.88188,...,7.6729)以及“ time =“(即00)后的值:00:09.12)。
我是grep / sed / awk的新手,试图学习如何使用其中之一来执行此操作,但是在苦苦挣扎之后,这只是没有发生。 我尝试过各种想法并在网上查看,但成功仍使我无法摆脱。 Python建议/解决方案也很好。 也尝试过,一团糟。
有人可以在这方面提供任何帮助吗? 我将不胜感激...谢谢您!!
使用GNU grep和Perl正则表达式 ( -P
):
grep -Po '(silence_start: |silence_end: |time=)\K[0-9:.]+' file
输出:
1.32515 1.88188 2.99698 3.42311 5.58311 6.13984 7.6729 00:00:09.12
gnu awk解决方案:
cat tst.awk
{ s=gensub(/.*(time=|silence_(start|end): )([0-9.:]+).*/, "\\3", "g");
print s
}
正则表达式说明:
.* # anything
( # group 1 start
time= # matching string "time="
| # OR
silence_(start|end): # matching string "silence_start: "
# or "silence_end: "
) # group 1 end
( # group 3 start
[0-9.:]+ # combination of number, "." and ":"
) # group 3 end
.* # anything
您可以将其用作:
$ awk -f tst.awk input.txt
1.32515
1.88188
2.99698
3.42311
5.58311
6.13984
7.6729
00:00:09.12
或作为一个班轮:
awk '{s=gensub(/.*(time=|silence_(start|end): )([0-9.:]+).*/, "\\3", "g"); print s}' input.txt
sed解决方案:
sed -E 's/.*(silence_(start|end): |time=)([^[:space:]]+).*/\3/' file
\\3
指向捕获的第三个括号(...)
组 输出:
1.32515
1.88188
2.99698
3.42311
5.58311
6.13984
7.6729
00:00:09.12
当您在输入中具有名称到值的映射时,一种解决方案会首先创建这些映射的数组(例如下面的n2v[]
),然后让您通过其名称访问值通常被证明是最健壮且将来最容易增强的解决方案当您的需求发生变化时:
$ cat tst.awk
BEGIN { FS="[ =]" }
{
for (i=1; i<=NF; i++) {
sub(/:$/,"",$i)
n2v[$i] = $(i+1)
}
prt("silence_start")
prt("silence_end")
prt("time")
}
function prt(name) {
if (name in n2v) {
print name, n2v[name]
delete n2v[name]
}
}
$ awk -f tst.awk file
silence_start 1.32515
silence_end 1.88188
silence_start 2.99698
silence_end 3.42311
silence_start 5.58311
silence_end 6.13984
silence_start 7.6729
time 00:00:09.12
如果只希望输出值name,
从打印行中删除name,
。
例如,如果您想将静默开始,结束和持续时间三倍地打印在每行的三行上,那将是微不足道的:
$ cat tst.awk
BEGIN { FS="[ =]" }
{
for (i=1; i<=NF; i++) {
sub(/:$/,"",$i)
n2v[$i] = $(i+1)
}
}
"silence_end" in n2v {
print n2v["silence_start"], n2v["silence_end"], n2v["silence_duration"]
delete n2v
}
END { print n2v["time"] }
$ awk -f tst.awk file
1.32515 1.88188 0.556735
2.99698 3.42311 0.426122
5.58311 6.13984 0.556735
00:00:09.12
上面的代码可以在任何UNIX安装环境(如果您有Windows的awk,则是Windows)上的任何shell中的任何awk上都可以使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.