linux - awk - 非重复值表

标签 linux bash shell unix scripting

用这个“|”分隔文件: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 持开放态度 它是每个字段的不同值(在“()”中对该值的出现次数进行计数,然后按这些出现次数降序排列):

已找到这 2 个代码片段,这些代码片段了解总体思路,但输出格式不同:

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

最佳答案

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/|*$//'

关于linux - awk - 非重复值表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8633329/

相关文章:

c++ - FLTK 1.4 小部件位置 w.r.t. X11 根窗口?

linux - shell脚本中字符串变量中的特殊字符

python - 如何使用内核名称(不是当前内核)获取内核版本

linux - VT-100 命令运行异常

bash - 为什么 "if [[ ... ]] then"(没有分号或换行符)在 ksh 中有效但在 bash 中无效?

bash - 检测是否安装了 homebrew 包

ios - 将 git head count 添加到 CFBundleVersion

macos - gfortran : fatal error: no input files compilation terminated

linux - 可用IP列表

linux - Beaglebone/Yocto/内核配置