【问题标题】:Awk - count similar words between linesawk - 计算行之间的相似词
【发布时间】:2013-06-11 19:12:28
【问题描述】:

我有自己无法解决的文本处理问题,因此我需要聪明人的帮助。
我的虚拟文件示例如下所示:

Winter    Sally    Additional_text
Winter    Sally    Additional_text
Winter    Nicole    Additional_text  
Spring    Lucy    Additional_text
Spring    Lucy    Additional_text
Spring    Caroline    Additional_text
Spring    Caroline    Additional_text
Summer    Emma    Additional_text
Autumn    Rita    Additional_text
Autumn    Rita    Additional_text
Autumn    Cristina     Additional_text
Autumn    Lucy's_sister     Additional_text
Autumn    Lucy's_sister     Additional_text

我想:
对于每个第一列项目,计算第二列中有多少不同的名称。但我只需要计算那些名称:1)至少出现两次并且 2)至少有两个不同的名称(它们都至少出现两次)。
对于这样的输出:

Time    Counts 
Spring    2
Autumn    2

输出说明:
Winter 中有两个不同的名称,但Nicole 只出现一次 - 未报告winter
Spring 中至少有两个不同的名称,并且每个名称至少出现两次 - 报告Spring 中有多少不同的名称;
Summer 中只有一个名字 - Summer 未报告;
Autumn 中,三个不同的名称,但其中只有两个至少出现两次 - 报告的计数仅针对 RitaLucy's_sister

编辑
我在 awk 和 bash 中的解决方案:

cut -d " " -f 1 FILE | sort -u > names
for i in $(cat names)
do 
   grep ^$i FILE | 
   awk '{print $2}' | 
   sort | 
   uniq -c | 
   awk -v VAR="$i" '($1>=2) {print VAR}' | 
   sort | 
   uniq -c | 
   awk '($1>=2) {print $2"\t"$1}' 
done

这太笨拙和重复了,所以我想知道更简单的方法。

【问题讨论】:

  • 你尝试过什么?

标签: bash awk


【解决方案1】:

这里是适合你的 awk 命令:

awk '{sums[$1"~"$2]++} END {for (a in sums) {split(a, b, "~"); if (sums[a]>1) suma[b[1]]++;}
      for (k in suma) if (suma[k]>1) print k, suma[k]}' inFile

【讨论】:

  • (sums[a]>1)(suma[k]>1) 是如何工作的? (1 是什么意思?)
  • >1 在这两种情况下都可以根据您的要求满足 count=2 的要求。
【解决方案2】:
awk '{kc[$1 "-" $2]++ } 
     END { for (k in kc) { if (kc[k]>=2) {f[gensub("-.*","","g",k)]++}}
           for (kk in f) { if (f[kk]>=2 ) {print kk, f[kk]}}}' INPUTFILE

会为你工作。首先,它计算数组中出现“FIRSTCOL-SECONDCOL”的次数。然后在每次出现的文件末尾检查出现次数,如果它大于一个,则将FIRSTCOL 存储在另一个数组中(作为键)并将其值加一。然后打印每个FIRSTVAL 及其大于一的值。我把标题留给你。

注意:如果第一列有任何“-”,它将失败。

【讨论】:

  • 如果你使用SUBSEP,你就不会有这个问题..
【解决方案3】:

这是使用GNU awk 的一种方式。运行如下:

awk -f ./script.awk file

script.awk的内容:

BEGIN {
    OFS="\t"
}
{
    a[$1][ b[$1,$2]++ ]++
}
END {
    print "Time", "Counts";
    for (i in a) {
        for (j in a[i]) {
            if (j >= 1 && a[i][j] >= 2) {
                print i, a[i][j]
            }
        }
    }
}

或者,这里是单行:

awk '{ a[$1][ b[$1,$2]++ ]++ } END { print "Time", "Counts"; for (i in a) for (j in a[i]) if (j >= 1 && a[i][j] >= 2) print i, a[i][j] }' OFS="\t" file

结果:

Time    Counts
Autumn  2
Spring  2

【讨论】:

    猜你喜欢
    • 2017-03-19
    • 2019-08-05
    • 2018-05-20
    • 1970-01-01
    • 2022-01-08
    • 2022-08-19
    • 2017-04-09
    • 2014-12-15
    • 1970-01-01
    相关资源
    最近更新 更多