【问题标题】:Discovering duplicate lines发现重复行
【发布时间】:2011-05-15 02:16:47
【问题描述】:

我有一个 CSS 元素文件,我正在尝试检查任何重复的 CSS 元素,.. 然后输出显示重复行的行。

###测试 ###ABC ###测试 ##。你好 ##.ABC ##。测试 bob.com###Test ~qwerty.com###Test ~more.com##.ABC

###Test & ##.ABC 已经存在于列表中,我想要一种输出文件中使用的行的方法,基本上是重复检查(区分大小写)。所以使用上面的列表,我会生成这样的东西..

第 1 行:###Test 第 7 行:bob.com###Test 第 8 行:~qwerty.com###Test 第 5 行:##.ABC 第 9 行:~more.com##.ABC

bash 中的东西,或者 perl 中的东西?

谢谢:)

【问题讨论】:

    标签: perl bash


    【解决方案1】:

    如果可以安装 MoreUtils,我建议使用 uniq 功能:

    how-do-i-print-unique-elements-in-perl-array

    【讨论】:

      【解决方案2】:

      我遇到了你的问题,所以我给你写了一个脚本。希望你喜欢它。 :)

      #!/usr/bin/perl
      
      use strict;
      use warnings;
      
      sub loadf($);
      
      {
          my @file = loadf("style.css");
          my @inner = @file;
          my $l0 = 0; my $l1 = 0; my $l2 = 0; my $dc = 0; my $tc;
          foreach my $line (@file) {
              $l1++;
              $line =~ s/^\s+//;
              $line =~ s/\s+$//;
              foreach my $iline (@inner) {
                  $l2++;
                  $iline =~ s/^\s+//;
                  $iline =~ s/\s+$//;
                  next if ($iline eq $line);
                  if ($iline =~ /\b$line\b/) {
                      $dc++;
                      if ($dc > 0) {
                          if ($l0 == 0) {
                              print "Line " . $l1 . ": " . $line . "\n";
                              $l0++;
                          }
                          print "Line " . $l2 . ": " . $iline . "\n";
                      }
                  }
              }
              print "\n" unless($dc == 0);
              $dc = 0; $l0 = 0; $l2 = 0;
          }
      }
      
      sub loadf($) {
          my @file = ( );
          open(FILE, $_[0] . "\n") or die("Couldn't Open " . $_[0] . "\n");
          @file = <FILE>;
          close(FILE);
          return @file;
      }
      
      __END__
      

      这正是您需要的。如果有点乱,请见谅。

      【讨论】:

      • 该脚本的问题太多,需要检查行尾,因此第 1781 行:##.test 第 1782 行:##.test-leaderboard 第 1787 行:##.abc 第 1788 行: ##.abcng 因为##.adc 与##.abcng 不同
      【解决方案3】:

      这似乎有效:

      sort -t '#' -k 2 inputfile
      

      它按#字符后的部分对它们进行分组:

      ##.ABC
      ~more.com##.ABC
      ###ABC
      ##.hello
      ##.test
      ###test
      bob.com###Test
      ~qwerty.com###Test
      ###Test
      

      如果您只想查看唯一值:

      sort -t '#' -k 2 -u inputfile
      

      结果:

      ##.ABC
      ###ABC
      ##.hello
      ##.test
      ###test
      ###Test
      

      这与问题中的示例输出非常相似(它依赖于一些可能特定于 GNU 的功能):

      cat -n inputfile | 
        sed 's/^ *\([0-9]\)/Line \1:/' |
        sort -t '#' -k 2 |
        awk -F '#+' '{if (! seen[$2]) { \
            if ( count > 1) printf "%s\n", lines; \
            count = 0; \
            lines = "" \
          }; \
          seen[$2] = 1; \
          lines = lines "\n" $0; ++count}
          END {if (count > 1) print lines}'
      

      结果:

      Line 5: ##.ABC
      Line 9: ~more.com##.ABC
      
      Line 1: ###Test
      Line 7: bob.com###Test
      Line 8: ~qwerty.com###Test
      

      【讨论】:

      • 我认为您在sort 的第一个示例中可能有错字。您是否可能打算输入sort -t '#' -k 2 inputfile(不带-u)?
      【解决方案4】:

      这是一种方法,如果需要,它很容易扩展到多个文件。

      有了这个文件find_dups.pl:

      use warnings;
      use strict;
      
      my @lines;
      while (<>) {                                     # read input lines
          s/^\s+//; s/\s+$//;                          # trim whitespace
          push @lines, {data => $_, line => $.} if $_  # store useful data
      }
      
      @lines = sort {length $$a{data} <=> length $$b{data}} @lines; # shortest first 
      
      while (@lines) {
          my ($line, @found) = shift @lines;
          my $re = qr/\Q$$line{data}\E$/;              # search token 
          @lines = grep {                              # extract matches from @lines
              not $$_{data} =~ $re && push @found, $_
          } @lines;
          if (@found) {                                # write the report
              print "line $$_{line}: $$_{data}\n" for $line, @found;
              print "\n";
          }
      }
      

      然后perl find_dups.pl input.css 打印:

      第 5 行:##.ABC 第 9 行:~more.com##.ABC 第 1 行:###测试 第 7 行:bob.com###Test 第 8 行:~qwerty.com###Test

      【讨论】:

      • 试过了,但它不检查行尾,例如,第 10476 行:test.com###plf-ysm 第 10477 行:test.com###plf-ysm-side不一样。否则它是一个不错的脚本:)
      • @user349418 => test.com###plf-ysm 包含在 test.com###plf-ysm-side 中,并根据您提供的测试数据进行匹配。我进行了编辑,可能会解决您遇到的问题,但下次请提供更多测试数据。此外,如果您认为您的问题的答案不错,您可以点击它旁边的向上箭头。
      猜你喜欢
      • 2014-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多