【问题标题】:Ignore lines with same next fields as previous忽略与上一个具有相同下一个字段的行
【发布时间】:2010-11-30 11:53:42
【问题描述】:

我有一个文件内容,看起来像这样

123,1,ABC,DEF
123,1,ABC
345,4,TZY
456,3,XYZ
333,4,TTT,YYY
333,4,TTT

我想忽略前后内容相同的行,即包含 123 和 333 的行

输出需要是

345,4,TZY
456,3,XYZ

关于如何解决这个问题的任何想法

【问题讨论】:

    标签: linux perl unix command


    【解决方案1】:

    试试 uniq 实用程序

    uniq -w 3 your_file.txt

    会成功的。不需要perl

    【讨论】:

    • 您需要添加 -u 标志以产生所需的输出(见问题)
    • 另外,uniq 的 -w 参数可能并非在每个 Unix 上都受支持(它不在 Solaris 10 上)
    【解决方案2】:

    TMTOWTDI:

    my $str = join '', <>;
    $str =~ s/^(\d+).+\n(\1.+\n)+//mg;
    print $str;
    

    编辑:第一行也可以替换为 Randal L. Schwartz 的 slurp:

    my $str = do { local $/; <HANDLE> }; # 
    

    【讨论】:

    • 真的很酷,但是在非常大的文件上性能会显着下降,因为你在啜饮。我在下面发布了一个持续使用内存的解决方案(尽管更加冗长且不那么酷)
    • 另外,根据 perl 最佳实践,您应该首先使用 File::Slurp 来 slurp 文件。
    • @DVK 是的,绝对不适合大文件。我试图想出一个巧妙的 map-grep-map 解决方案来解决这个问题,但它很快就变得丑陋了。还在考虑中……
    【解决方案3】:

    TMTOWDI

    my $last_prefix = ""; 
    my $last_line = ""; 
    while (<>) { check_line($_); }
    check_line("");    sub check_line {
        my $line = shift;
        my ($prefix) = ($line =~ /^([^,]*),/); 
        if (($prefix || "") ne $last_prefix ) {
            print $last_line;
            $last_line = $_;
        } else {
            $last_line = "";
        };
        $last_prefix = $prefix; 
    
    }
    

    这很罗嗦,但我怀疑在非常大的文件上性能可能比正则表达式更好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多