用这个“|”分隔文件:dummy.dat
sid|storeNo|latitude|longitude
2|1|-28.03720000
9|2
10
jgn352|1|-28.03720000
9|2|fdjkjhn422-405
0000543210|gfdjk39
例如,纬度字段中的值“-28.03720000”出现两次,然后在输出中它将出现一次但在其结尾处(2)。另一个例子,值“2”在sid字段中出现一次但在storeno字段中出现两次 - 因此对于输出,它将在sid字段下面有一个条目(在末尾带有“(1)”)和storeno下面的一个条目字段(末尾有“(2)”)。
期望的结果:
sid|storeNo|latitude|longitude
9(2)|1(2)|-28.03720000(2)
0000543210(1)|2(2)|fdjkjhn422-405(1)
10(1)|gfdjk39(1)
2(1)
jgn352(1)
可接受的期望结果的另一个例子(给定相同的输入文件):
sid|storeNo|latitude|longitude
9(2)|2(2)|-28.03720000(2)
jgn352(1)|1(2)|fdjkjhn422-405(1)
10(1)|gfdjk39(1)
0000543210(1)
2(1)
产生上述输出的通用解决方案是什么?我对awk,bash,perl.etc持开放态度 它是每个字段的不同值(具有“()”中该值的出现次数,然后按出现次数排序desc):
找到了这两个代码片段,它们提供了一般性的想法,但只是采用不同的输出格式:
Script 1:
awk -F"|" ' {
for( i = 1; i <= NF; i++ )
{
count[i " " $(i)]++; # count by field number and field value
uniq[$(i)] = 1; # save a list of unique strings
}
if( NF > fields )
fields = NF; # in case a variable number in file; capture max
}
END {
for( i = 1; i <= fields; i++ )
{
printf( "field %d\n", i );
for( x in uniq )
if( count[i " " x] )
printf( "%s (%d)\n", x, count[i " " x] ); # print by field and value
printf( "\n" );
}
} ' dummy.dat
Script 2:
awk -F"|" '{for (i=1;i<=NF;i++) a[i FS $i]++} END {for (i in a) print i,"(",a[i],")" |"sort -n" } ' dummy.dat
答案 0 :(得分:2)
awk -F'|' '
FNR==NR{
if(FNR>1)
for(i=1;i<=NF;i++)
a[$i,i]++
next
}
FNR==1{print}
FNR>1{
for(j=1;j<=NF;j++)
if(b[$j,j]++)
printf("|")
else
printf("%s(%s)|",$j,a[$j,j])
print ""
}' ./dummy.dat ./dummy.dat | sed 's/|*$//'
sid|storeNo|latitude|longitude
2(1)|1(2)|-28.03720000(2)
9(2)|2(2)
10(1)
jgn352(1)
||fdjkjhn422-405(1)
0000543210(1)|gfdjk39(1)
注意: 摆脱尾随 |
将需要额外的工作。希望这就足够了。
我刚刚将最终输出传递给sed 's/|*$//'