【问题标题】:bash sum grouping loopbash sum 分组循环
【发布时间】:2014-05-28 12:25:19
【问题描述】:

我有一个格式的帮助文件1:

client1 bla blahblah 2542 KB
client1 bla blahblah 4342 MB
client1 bla blahblah    7 GB

client2 bla blahblah  455 MB
client2 bla blahblah  455 MB

...

而且我需要获得周码

client1 SUM xy KB
client2 SUM yx KB

目前我正在使用:

sumfunction ()
    {
    inputfile=helpfile1

    for i in `awk -F":" '{print $1}' $inputfile| sort -u | xargs`
    do
    awk -v name=$i 'BEGIN {sum=0};
    $0~name {
    print $0;
    if ($5 == "GB") sum = sum + $4*1024*1024;
    if ($5 == "MB") sum = sum + $4*1024;
    if ($5 == "KB") sum = sum + $4};
    END {print name " SUM " sum " kB"}' $inputfile
    done
    }   

sumfunction | grep SUM | sort -g -r -k 3 > weeklysize

我需要在相当长的文件上使用它,而这个 awk 占用了太多时间。是否有其他代码(仅限 bash)可以更快地完成这项工作?谢谢

【问题讨论】:

  • 如何改变helpfile1中的信息写入方式?
  • 好代码,好问题,只是由于缺乏你的设置期望而受到阻碍。你是什​​么意思'太多时间',1秒,2分钟,3小时,4天?有多少“记录”(由wc -l tooBigFile 获得)以及您在哪种硬件上运行它。虽然快 2 倍就足够了? e 尝试从您的名字 arg 和锚点在行的开头创建一个 reg ex,然后您不会扫描整行以匹配仅在开头的内容,即。 name="^"$1 ; $0~name 或者为什么不只是 $1=-name { ... 祝你好运。
  • @shellter 你确定你在正确的电影中吗?
  • @hek2mgl :是的,我想是的,引用 O.P. “而且这个 awk 花费了太多时间”。我喜欢你的解决方案,但谁知道 OP 是否会,也许它太慢了。祝你们好运 ; -)
  • @shellter 好的,知道了 :) 但是,我或 Adrian 的解决方案不应该花费太多时间,而且不,时间不是相对的 ;)

标签: bash loops awk grouping


【解决方案1】:
#!/usr/bin/awk -f

BEGIN {
    output_unit = "KB"
    modifier["KB"] = 1
    modifier["MB"] = 1024
    modifier["GB"] = 1024**2
}
NF  { sums[$1] += modifier[$5] * $4 }
END {
    for (client in sums) {
        printf "%s SUM %d %s\n", client, sums[client]/modifier[output_unit], output_unit
    }
}

注意事项:

  • 将跳过空白行 (NR { [...] })
  • 输出单元可通过设置output_unit相应地配置(KBMBGB

$ ./t.awk t.txt
client1 SUM 11788782 KB
client2 SUM 931840 KB

【讨论】:

    【解决方案2】:

    您可以使用以下 awk 脚本:

    awk '/MB$/{$4*=1024};/GB$/{$4*=1024*1024};{a[$1]+=$4}END{for(i in a){printf "%s %s KB\n",i, a[i]}}' a.txt 
    

    这种格式看起来更好:

    /MB$/    {$4*=1024};        # handle MB
    /GB$/    {$4*=1024*1024};   # handle GB
    
    # count KB amount for the client
    {a[$1]+=$4}
    
    END{
        for(i in a){
            printf "%s %s KB\n",i, a[i]
        }
    } 
    

    输出

    client1 11788782 KB
    client2 931840 KB
    

    【讨论】:

      【解决方案3】:

      Pure Bash (4.0+):

      declare -Ai client                  # associative array
      
      while read c1 c2 c3 c4 c5 ; do
        if [ -n "$c5" ] ; then
          if [ $c5 = 'KB' ] ; then
            client[$c1]+=$c4
          elif [ $c5 = 'MB' ] ; then
            client[$c1]+=$c4*1024
          elif [ $c5 = 'GB' ] ; then
            client[$c1]+=$c4*1024*1024
          fi
        fi
      done < "$infile"
      
      for c in ${!client[@]}; do          # print sorted results
        printf "%s %20d KB\n" $c ${client[$c]}
      done | sort  -k1
      

      输出

      client1             11788782 KB
      client2               931840 KB
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-02-04
        • 1970-01-01
        • 2012-03-31
        • 1970-01-01
        • 1970-01-01
        • 2014-04-09
        • 1970-01-01
        相关资源
        最近更新 更多