【问题标题】:Unix shell - manipulation and filtering of textUnix shell - 文本的操作和过滤
【发布时间】:2018-11-22 16:59:36
【问题描述】:

我正在尝试使用 Unix shell 解决任务。我有以下输出:

  2 Accepted 10.0.0.202
  8 Failed 10.0.0.202
 11 Failed 10.0.0.202
  1 Accepted 151.62.163.222
  3 Failed 151.62.163.222

我想找出每个 IP 地址的失败次数和接受次数,并像这样打印:IP-adr failedAttempts acceptedAttempts。

有人对我如何解决这个问题有任何意见吗?

【问题讨论】:

    标签: shell unix filter terminal


    【解决方案1】:

    GNU awk 有数组数组,所以很简单:

    processToProduceOutput | gawk '
        {count[$3][$2] += $1} 
        END {
            for (ip in count)
                print ip, 0 + count[ip]["Accepted"], 0 + count[ip]["Failed"]
        }
    '
    

    产生

    151.62.163.222 1 3
    10.0.0.202 2 19
    

    要使输出更漂亮,请输入| column -t

    0 + count... 将允许没有接受/失败的 IP 在相应的列中显示 0。


    还有这个过于聪明的perl

    perl -lane '
        $c{$F[2]}{$F[1]} += $F[0];
    }{ 
        printf "%s %d %d\n", $_, map {0+$_} $c{$_}->@{"Accepted","Failed"} for keys %c;
    '
    

    【讨论】:

      【解决方案2】:

      这可以通过GNU Datamash 1.3 及其crosstab/pivot 操作相当优雅地完成:

      $ datamash -W crosstab 3,2 sum 1 < data
              Accepted        Failed
      10.0.0.202      2       19
      151.62.163.222  1       3
      

      【讨论】:

        【解决方案3】:

        我添加了一个 ip 用于测试边缘情况:

        (pi 695) $ cat /tmp/x 
         2 Accepted 10.0.0.202
          8 Failed 10.0.0.202
         11 Failed 10.0.0.202
          1 Accepted 151.62.163.222
          3 Failed 151.62.163.222
        111 Failed 8.8.8.8
        222 Failed 8.8.8.8
        (pi 696) $ awk '
          {ip[$3]++}                  # keep track of ALL ip addresses
          $2=="Accepted" {a[$3]+=$1}  # keep track of all Accepted
          $2=="Failed"   {f[$3]+=$1}  # keep track of all Failed
          END{
            for(i in ip){             # for every ip seen
              print i, f[i]+0, a[i]+0 # print ip, failures, and accepts
            }
          }' /tmp/x
        151.62.163.222 3 1
        8.8.8.8 333 0
        10.0.0.202 19 2
        

        【讨论】:

        • 请在您的 awk 中添加一些空格
        【解决方案4】:

        以下AWK 脚本可用于执行该任务。将脚本保存在文件中,然后运行 ​​bash 命令:$ awk -f scipt_file text_file

        {
            if ($2 == "Failed") {
                if ($3 in failed)
                    failed[$3] += $1
                else 
                    failed[$3] = $1
            }
        
            else {
                if ($3 in accepted)
                    accepted[$3] += $1
                else
                    accepted[$3] = $1
            }
        }
        
        END {
            printf "%-16s\t%s\t%s\n", "IP", "Failed", "Accepted"
            for (ip in accepted) {
                if (ip in failed) {
                    nfail = failed[ip] 
                } else 
                    nfail = 0
                printf "%-16s\t%d\t%d\n", ip, nfail, accepted[ip]
            }
        
            for (ip in failed) {
                if (ip in accepted) {} 
                else {
                    printf "%-16s\t%d\t%d\n", ip, failed[ip], 0 
                } 
            }
        }
        

        打印出来:

        IP                      Failed  Accepted
        151.62.163.222          3       1
        10.0.0.202              19      2
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-01-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-20
          • 1970-01-01
          相关资源
          最近更新 更多