【问题标题】:Extracting floats from lines with irregular surrounding text从具有不规则周围文本的行中提取浮点数
【发布时间】:2018-02-25 08:42:14
【问题描述】:

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

[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 建议/解决方案也很棒。也试过了,结果一团糟。

有人可以提供任何帮助吗?我将不胜感激...提前谢谢您!

【问题讨论】:

  • 你能展示你到目前为止的挣扎吗?有人可以帮助修复它们...

标签: python awk sed grep floating-point


【解决方案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

【讨论】:

    【解决方案2】:

    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
    

    【讨论】:

      【解决方案3】:

      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
      

      【讨论】:

        【解决方案4】:

        当您的输入中有名称到值的映射时,首先创建这些映射数组的解决方案(例如下面的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 安装(或 Windows,如果您有适用于 Windows 的 awk)上的任何 shell 中的任何 awk。

        【讨论】:

          猜你喜欢
          • 2010-12-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-04-22
          • 1970-01-01
          相关资源
          最近更新 更多