打印整行,当发现重复

Print whole lines, when find duplicate

这是我输入的片段:

DGD3 SOL10
DGD53 SOL15
DGD100 SOL15
DGD92 SOL20
DGD41 SOL22
DGD62 SOL35
DGD13 SOL40
DGD13 SOL40

我的预期输出

DGD53 SOL15
DGD100 SOL15
DGD13 SOL40
DGD13 SOL40

在我的数据中,我有时会有 SOL 重复(不超过两次重复,例如文件中某个 SOL 的三倍,但只有重复)。 SOL 在我的第二列中($2)。因此,当我发现重复的 SOL ($2) 时,我需要一个打印整行(DGD 和 SOL)的程序。你能帮帮我吗?

使用您的示例(按第二个字段排序),您可以:

$ awk 'l2=={print ll; print; next}
       {ll=[=10=]; l2=}' file

打印:

DGD53 SOL15
DGD100 SOL15
DGD13 SOL40
DGD13 SOL40

这类似于仅打印相邻重复项的 Unix uniq 过滤器。

如果文件中的重复项是随机的,您可以先排序:

$ awk 'l2=={print ll; print; next}
            {ll=[=12=]; l2=}' <(sort -k 2 file) 

或者,对文件进行两次传递:

$ awk 'FNR==NR{cnt[]++; next} cnt[]>1' file file

或者,要仅识别 2 个或更多个 SOL 标签,您可以这样做:

$ awk '++cnt[]==2' file   

并且您可以使用相同的方法生成 grepsed 的命令代码,以从未排序的文件打印:

$ sed -n -f <(awk '++cnt[]==2 {printf "/[[:space:]]%s$/p\n", }' file) file

所以选择是:

  1. 使用更多内存(通过将整个文件缓存在以 为键值的内存中),或者
  2. 先排序,或者
  3. 遍历文件两次。

您可以使用此 awk,它将打印重复项 不一定是相邻的

awk ' in map {print map[] ORS [=10=]} {map[] = [=10=]}' file

DGD53 SOL15
DGD100 SOL15
DGD13 SOL40
DGD13 SOL40

添加另一种 awkish 风格的方式,在 Input_file 的第一次读取中获取所有值计数并在第二次读取中根据它们的计数打印所有值。公平警告,这可能不如其他 2 个解决方案快,但从理解的角度来说应该很简单。

awk '
FNR==NR{
  count[]++
  next
}
(count[]>1)
' Input_file  Input_file

如果您的文件在第二个字段中排序 uniq 专为此任务而设计,具有正确的选项。

$ uniq -f1 -D file

DGD53 SOL15
DGD100 SOL15
DGD13 SOL40
DGD13 SOL40

跳过第一个字段,打印所有重复项...

另一个awk。单个 运行,不需要对文件进行排序,如果第二个字段的实例超过 2 个,则可以正常工作。在最坏的情况下,它会在内存中散列整个文件并且不会产生任何输出:

$ awk '{
    if(!c[]++)           # if first instance of 
        a[]=[=10=]           # store it
    else {
        if(c[]==2) {     # if second instance 
            print a[]    # print previous
            delete a[]   # no need to waste my memory any more
        } 
        print              # after first instance of  we always print current
    }
}' file

输出:

DGD53 SOL15
DGD100 SOL15
DGD13 SOL40
DGD13 SOL40