从具有不规则周围文本的行中提取浮点数

时间:2017-09-16 08:11:53

标签: python awk sed grep floating-point

我有一个包含以下内容的文本文件:

[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建议/解决方案也很棒。也试过,这很乱。

有人可以请你提供任何帮助吗?我非常感谢...提前谢谢!!

4 个答案:

答案 0 :(得分:1)

使用GNU grep和Perl regular expression-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

答案 1 :(得分:0)

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

或作为oneliner:

 awk '{s=gensub(/.*(time=|silence_(start|end): )([0-9.:]+).*/, "\\3", "g"); print s}' input.txt

答案 2 :(得分:0)

sed 解决方案:

sed -E 's/.*(silence_(start|end): |time=)([^[:space:]]+).*/\3/' file
  • \3 - 指向第3个带括号的(...)群组

输出:

1.32515
1.88188
2.99698
3.42311
5.58311
6.13984
7.6729
00:00:09.12

答案 3 :(得分:0)

如果您的输入中有值映射的名称,那么首先创建这些映射数组的解决方案(例如下面的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,

例如,如果您想在每行1行打印静音开始,结束和持续时间三元组,那将是微不足道的:

$ 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安装的任何shell中的任何awk(如果你有Windows的awk,则适用于Windows)。