试试这个 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