【问题标题】:Awk issue, duplicate lines in multiple files at once.awk 问题,一次在多个文件中重复行。
【发布时间】:2016-05-26 00:20:58
【问题描述】:

我对下面的格式输出有疑问。

我在许多文件 SHORT_LIST.a SHORT_LIST.b SHORT_LIST.c 中有重复的行,但可能还有很多很多。

“test1”行存在于所有三个文件中,字符串“sample”也是如此。

“test”行存在于两个文件中,但在其中一个文件中存在不止一次,我想让它在每个文件名中只输出一次。

function check_duplicates {

 awk 'END {
   for (R in rec) {
   #split out the SHORT_LIST files
    n = split(rec[R], t, "/SHORT_LIST")
    #printf n dup[n]
    count = 0
if  ( n > 2 )
 dup[n] = dup[n] ? dup[n] RS sprintf( R, rec[R]) :
   sprintf("\t%-20s %s ", R, rec[R]);
}
for (D in dup) {
  ((count++))
   printf "%s\n \n", d
   printf count " ). Duplicate record(s) found in the following files: " dup[D]
     }
   }
{
   # build an array named rec (short for record), indexed by
   # the content of the current record ($0), concatenating
   # the filenames separated by / as values
   rec[$0] = rec[$0] ? rec[$0] "\n \t" FILENAME : FILENAME
   }' $SITEFILES

  }

check_duplicates

当前输出如下:

在以下文件中发现重复记录:

1)。在以下文件中发现重复记录:test1
SHORT_LIST.a SHORT_LIST.b SHORT_LIST.c 样本

2)。在以下文件中发现重复记录:test
SHORT_LIST.c SHORT_LIST.b SHORT_LIST.b SHORT_LIST.b

3)。在以下文件中发现重复记录:/path/to/file
SHORT_LIST.a SHORT_LIST.c 睾丸

期望的输出如下:

在以下文件中发现重复记录:

1)。在以下文件中发现重复记录:test1
SHORT_LIST.a SHORT_LIST.b SHORT_LIST.c

2)。在以下文件中发现重复记录:示例
SHORT_LIST.a SHORT_LIST.b SHORT_LIST.c

3)。在以下文件中发现重复记录:test
SHORT_LIST.c SHORT_LIST.b

4)。在以下文件中发现重复记录:/path/to/file
SHORT_LIST.a SHORT_LIST.c

5)。在以下文件中发现重复记录:testa SHORT_LIST.a SHORT_LIST.c

任何建议都将不胜感激,我在这个级别的 AWK 上遇到了问题。

【问题讨论】:

  • 我不确定这有什么帮助?我需要列出重复项及其所在的每个文件。
  • 删除我原来的评论。也许像sort -o file.srt file ; sort file2.srt file2 ; comm -12 file.srt file2.srt >file1_2.comm; awk '{print "Dupes :"$0}' file1_2.comm 这样的东西可以让你使用标准工具,而不是“重新发明轮子”;-)。您必须花时间阅读有关 comm 的信息,以确定您是否可以使其输出适合您。祝你好运。
  • 问题是,我通过 $SITEFILES 传入预定文件,它们在开始时被传递到一个更大的脚本中,并且可以按名称、日期、大小等进行排列,所以我可以'不仅仅是给它一些文件名,因为有时我会有一个文件,有时我可能有 5000 个文件,这取决于前面的处理过程。
  • @ben,发布一些示例文件会更容易为您提供帮助。

标签: linux bash awk duplicates printf


【解决方案1】:
You can follow this template and fix the output format as desired

$ awk -f dups.awk fa fb fc

dups for : /path/to/file in files
fa fc
dups for : test in files
fa fb fc
dups for : sample in files
fa fb fc
no dups in
fc

$ cat dups.awk

  FNR==1{files[FILENAME]}
        {if((FILENAME, $0) in a) dupsInFile[FILENAME]
         else
           {a[FILENAME, $0]
            dups[$0] = $0 in dups ? (dups[$0] FS FILENAME) : FILENAME
            count[$0]++}}
     END{for(k in dups)
           {if(count[k] > 1)
              {print ("dups for : " k) " in files"
               print dups[k]}}
        for(f in dupsInFile) delete files[f];
        print "no dups in";
        for(f in files) printf "%s", f FS;
        printf "\n";
     }

在哪里

$ head f{a,b,c}
==> fa <==
test
test
test1
sample
/path/to/file

==> fb <==
test
test
sample

==> fc <==
test
sample
/path/to/file

ps。始终提供样本输入。

【讨论】:

  • 哇,谢谢,这太完美了! - em,知道如何在同一个文件中找到骗子吗?或者我如何在文件名之间添加换行符?即“fa”\n“fb”\n“fc”
  • 即fb 在那里进行了两次测试,对于这些文件中的每一行,都会启动一个作业,因此在每个文件中捕获重复项也很重要。如果这有意义吗?
  • 我从您的“测试行存在...每个文件名只输出一次”的理解。声明是您不想报告文件中的重复项。
  • 哦,抱歉,翻译丢失了,我想 A)报告多个文件中的重复项,以及 B)报告每个文件中的重复项。我希望这是有道理的。另外,出于好奇,其中包含文件名的数组 dups[k] ,知道如何将这些元素分别打印在一行上吗?
  • 您的格式是单行:对于每个文件名的单独行:将“FS”替换为“RS”。对于同一文件中的重复项,您可以使用 dupsInFile 数组处理该部分,该数组将文件名保留在存在重复项的位置。将条目存储在另一个按文件名索引的数组中,类似于 dups 数组。
【解决方案2】:

可能是这样的

 awk '{print FILENAME "\t" $0}' $SITEFILES \
 | sort \
 | uniq -c -f1 \
 | awk "{if ($1 + .0 != 1) print $0}'

让你开始

没有小样本数据集,在这方面做更多是不切实际的。

IHTH

【讨论】:

    【解决方案3】:

    我将其拆分为多个文件,在同一个文件中,我还放入了一些内容以允许忽略 cmets,您也可以使用空格来执行此操作,等等。

    非常感谢@karakfa,您的回答非常棒,谢谢。

    function check_duplicates {
     #Check multiple files for duplicates.   
      awk '
       FNR==1{files[FILENAME]}
              {if((FILENAME, $0) in a) dupsInFile[FILENAME]
               else
                 {a[FILENAME, $0]
                  dups[$0] = $0 in dups ? (dups[$0] RS FILENAME) : FILENAME
                  count[$0]++}}
                  #ignore comment lines
                   {if ($0 ~ /#/) {
                       delete dups[$0]
                    }}
      #Print duplicates in more than one file
              END{for(k in dups)
                 {if(count[k] > 1)
                   {print ("\n\n\tDuplicate line found: " k) "\n\tIn the following file(s)"
                     print dups[k] }}
              printf "\n";
    
    
           }' $SITEFILES
     #Check single files for duplicates.    
     awk '
     NR {
         b[$0]++
        }
        #ignore comment lines
            $0 in b {
               if ($0 ~ /#/) {
               delete b[$0]
                             }
                          if (b[$0]>1) {
                          print ("\n\n\tDuplicate line found: "$0) "\n\tIn the following file"
                          print FILENAME
                          delete b[$0]
                          }
        }' $SITEFILES
    
    
      }
    

    【讨论】:

      猜你喜欢
      • 2016-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-17
      • 2015-12-05
      • 1970-01-01
      • 2016-06-17
      • 2014-04-09
      相关资源
      最近更新 更多