【问题标题】:awk sort count values sum duplicates and transpose columnsawk 排序计数值求和重复和转置列
【发布时间】:2019-06-12 06:31:34
【问题描述】:

我正在玩这个以获得更易于阅读的格式的输出,因为尝试基于 uniq 列 nr4 和 nr2 其中 OK 是状态,X 是“KO”状态, 它属于 nr1 列,其中并非所有时间甚至规则都具有 F1 F2 .. nr.3 中的值的 OK 状态。

开始使用此输入:

输入:

NR5X1 OK F1 SEAT5
NR5X1 OK F2 SEAT5
NR5X1 X F3 SEAT5
NR5X1 X F4 SEAT5
NR5X1 X F5 SEAT5
NR5X1 X F6 SEAT5
NR5X1 X F7 SEAT5
NR5X1 X F8 SEAT5
NR5X2 OK F1 SEAT5
NR5X2 OK F2 SEAT5
NR5X2 X F3 SEAT5
NR5X2 X F4 SEAT5
NR5X2 X F5 SEAT5
NR5X2 X F6 SEAT5
NR5X2 X F7 SEAT5
NR5X2 X F8 SEAT5
NR5X3 OK F5 FLEET
NR5X3 OK F6 FLEET
NR5X5 OK F5 FLEET
NR5X5 OK F6 FLEET
NR5X7 F5 X ROME
NR5X7 F6 X ROME
NR5X8 F5 X ROME
NR5X8 F6 OK ROME

并试图实现这个输出

2 OK of 8 | SEAT5 NR5X1 OK F1 OK F2 X F3 X F4 X F5 X F6 X F7 X F8
2 OK of 8 | SEAT5 NR5X2 OK F1 OK F2 X F3 X F4 X F5 X F6 X F7 X F8
2 OK of 2 | FLEET NR5X3 OK F5 OK F6
2 OK of 2 | FLEET NR5X5 OK F5 OK F6
2 X  of 2 | ROME  NR5X7 X  F5 X  F6
1 OK of 2 | ROME  NR5X8 X  F5 OK F6

使用此代码部分移动:

cat file | awk '!seen[$1]++ {print $4,$1} {print $3,$2}',多个名称上的xargs 将全部加入一行,所以我卡在这里

ROME NR5X7
X F5
X F6
ROME NR5X8
X F5
OK F6

不确定是否有其他简单的方法来美化输出,但事实上这是最后需要的东西

欢迎提出任何建议,美好的一天

【问题讨论】:

  • 不清楚你的输出第一列是怎么来的,请解释一下。
  • @RavinderSingh13 从系统第 1 列开始设置,表示每次在 F1-F8 范围内都应该是唯一的一对

标签: sorting awk count multiple-columns transpose


【解决方案1】:
$ cat tst.awk
$1 != prev {
    if (NR > 1) {
        prt()
    }
    prev = $1
}
{
    key  = $1
    type = $4
    if (type == "ROME") {
        stat = $3
        fval = $2
    }
    else {
        stat = $2
        fval = $3
    }
    statCnt[stat]++
    totCnt++
    pairs = pairs OFS sprintf("%-2s %-2s",stat,fval)
}
END { prt() }
function prt(   stat) {
    stat = ("OK" in statCnt ? "OK" : "X")
    printf "%d %-2s of %d | %-5s %s%s\n", statCnt[stat], stat, totCnt, type, key, pairs
    delete statCnt
    totCnt = 0
    pairs  = ""
}

.

$ awk -f tst.awk file
2 OK of 8 | SEAT5 NR5X1 OK F1 OK F2 X  F3 X  F4 X  F5 X  F6 X  F7 X  F8
2 OK of 8 | SEAT5 NR5X2 OK F1 OK F2 X  F3 X  F4 X  F5 X  F6 X  F7 X  F8
2 OK of 2 | FLEET NR5X3 OK F5 OK F6
2 OK of 2 | FLEET NR5X5 OK F5 OK F6
2 X  of 2 | ROME  NR5X7 X  F5 X  F6
1 OK of 2 | ROME  NR5X8 X  F5 OK F6

【讨论】:

    【解决方案2】:

    试试这个 Perl 解决方案

    $ seats.ksh ya801.txt
    2 OK of 2 | FLEET NR5X3 OK F5 OK F6
    1 OK of 2 | ROME NR5X8 X F5 OK F6
    2 OK of 2 | FLEET NR5X5 OK F5 OK F6
    2 OK of 8 | SEAT5 NR5X1 OK F1 OK F2 X F3 X F4 X F5 X F6 X F7 X F8
    2 X of 2 | ROME NR5X7 X F5 X F6
    2 OK of 8 | SEAT5 NR5X2 OK F1 OK F2 X F3 X F4 X F5 X F6 X F7 X F8
    

    脚本:

    $ cat seats.ksh
    perl -lane '
    $x="$F[3] $F[0]";
    $kv{$x}++;
    @t=@{$kv2{$x}};
    push(@t,"$F[1] $F[2]");
    $kv2{$x}=[@t];
    @tok=@{$kvok{$x}};
    if ( $F[1] eq "OK" ) { push(@tok,$F[1]); $kvok{$x}=[@tok] }
    @tx=@{$kvx{$x}};
    if ( $F[1] eq "X" ) { push(@tx,$F[1]); $kvx{$x}=[@tx] }
    END
    {
            foreach $p (keys %kv)
            {
             @oks=@{$kvok{$p}};
             @xs=@{$kvx{$p}};
             if( scalar @oks ) { $okcount=sprintf("%d OK of %d | ",scalar @oks, $kv{$p}) }
             else { $okcount=sprintf("%d X of %d | ",scalar @xs, $kv{$p}) }
             print $okcount, "$p ", join(" ",@{$kv2{$p}})
            }
    }
    ' $1
    $
    

    注意:看起来第 2 列和第 3 列在最后 4 行中交换了..所以我更改了它们

    $ cat ya801.txt
    NR5X1 OK F1 SEAT5
    NR5X1 OK F2 SEAT5
    NR5X1 X F3 SEAT5
    NR5X1 X F4 SEAT5
    NR5X1 X F5 SEAT5
    NR5X1 X F6 SEAT5
    NR5X1 X F7 SEAT5
    NR5X1 X F8 SEAT5
    NR5X2 OK F1 SEAT5
    NR5X2 OK F2 SEAT5
    NR5X2 X F3 SEAT5
    NR5X2 X F4 SEAT5
    NR5X2 X F5 SEAT5
    NR5X2 X F6 SEAT5
    NR5X2 X F7 SEAT5
    NR5X2 X F8 SEAT5
    NR5X3 OK F5 FLEET
    NR5X3 OK F6 FLEET
    NR5X5 OK F5 FLEET
    NR5X5 OK F6 FLEET
    NR5X7 X F5 ROME 
    NR5X7 X F6 ROME
    NR5X8 X F5 ROME
    NR5X8 OK F6 ROME
    $
    

    说明:

    perl -lane '
    $x="$F[3] $F[0]";  # Capture 4 & 1 col together
    
    $kv{$x}++; # hash "kv" for the overall count i.e the 8 in "2 OK of 8"
    
    @t=@{$kv2{$x}};  # dereference the array in @t i.e 2nd and 3rd column together 
    push(@t,"$F[1] $F[2]"); # append to the array with new value if 2 & 3 col together
    $kv2{$x}=[@t]; # reassign it bact to hash "kv2"
    
    @tok=@{$kvok{$x}};  # dereference the array in @tok for capturing OK 
    if ( $F[1] eq "OK" ) { push(@tok,$F[1]); $kvok{$x}=[@tok] }  # append only if "OK" is present in the 2nd column =>  uses hash kvok
    
    @tx=@{$kvx{$x}};  # dereference the array in @tx for capturing X 
    if ( $F[1] eq "X" ) { push(@tx,$F[1]); $kvx{$x}=[@tx] }  # append only if "X" is present in the 2nd column => uses hash kvx
    END
    {
            foreach $p (keys %kv)  # loop through the kv hash
            {
    
             @oks=@{$kvok{$p}}; # dereference and get the OK array from kvok hash
             @xs=@{$kvx{$p}}; # dereference and get the X array from kvx hash
    
             if( scalar @oks ) { $okcount=sprintf("%d OK of %d | ",scalar @oks, $kv{$p}) }  # scalar @oks gives the array size. Only if the OK count is > 1 then print like "2 OK of 8"
             else { $okcount=sprintf("%d X of %d | ",scalar @xs, $kv{$p}) }   # false then ise the X array
    
             print $okcount, "$p ", join(" ",@{$kv2{$p}})  # print all of them together hash kv2 contains the arrays of 2&3 col together
    
            }
    }
    ' $1
    

    【讨论】:

    • 是否有可能以某种方式放置一些 cmets ?我正在尝试找到一些易于阅读的 sefl 解释格式,例如在 awk 中我有点迷失在那个 perl 代码中,但它可以工作,非常感谢,这可能适应 awk 吗?尝试使用@RavinderSingh13 代码进行一些调整
    • 它使用 Perl 的引用特性来追加数组。我会添加它
    • 添加了解释..不要被语法吓倒..这需要一些时间来学习,但真的很值得.. Perl 可以做的事情比 awk 更多。
    • @ya801,请让我知道我在 cmets 中的awk 解决方案的问题在哪里?
    • @RavinderSingh13 嗨,没有问题,我用“ROME”删除了部分,并尝试对每个 F1 F2 的结果进行聚合(这两个值正在创建 GROUP1),依此类推外汇价值
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    • 2021-03-17
    • 1970-01-01
    • 2015-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多