【问题标题】:Group matching lines in a text file together将文本文件中的匹配行组合在一起
【发布时间】:2014-06-27 13:16:03
【问题描述】:

我有一个输入文件:

XYZ_001
XYZ_005
XYZ_010
ABC_001
ABC_010

我想将这些行分组为:

XYZ,XYZ_001,XYZ_005,XYZ_010
ABC,ABC_001,ABC_010

我已尝试对文件进行排序并过滤掉最后四个字符,但我不知道如何将它们组合在一起。基本上,我需要将匹配正则表达式的行组合在一起。我的输入文件已排序。

我的文件很大。我不能吞下整个文件。

【问题讨论】:

标签: regex linux perl grep


【解决方案1】:

使用 perl 单行代码

perl -0777 -pe 's/^([^_]+_).*\K\n(?=\1)/,/mg; s/^([^_]*)\K/,$1/mg;' file

如果啜饮不是一种选择,那么这种较长形式的逻辑将起作用:

perl -ne '
      chomp;
      ($h) = /([^_]*)/;
      if ($l ne $h) {print "\n" if defined $l; $l = $h; print "$l"}
      print ",$_";
    }{
      print "\n"
    ' file

说明:

开关

  • -0777:啜饮整个文件
  • -p:为输入文件中的每个“行”创建一个 while(<>){...; print} 循环。
  • -e:告诉perl 在命令行上执行代码。

代码

  • s/^([^_]+_).*\K\n(?=\1)/,/mg:分组相关邻线:XYZ_001,XYZ_005,XYZ_010
  • s/^([^_]*)\K/,$1/mg:添加组前缀:XYZ,XYZ_001,XYZ_005,XYZ_010

【讨论】:

  • 感谢您的回答。我的文件很大。我不能吞下整个文件。
  • @Ari 好的。如果你不能啜饮,我建议第二个选择。
  • @Ari 请注意,目前提出的所有其他解决方案也将整个文件加载到内存中,除了它们使用 5 倍的内存,因为数据被加载到哈希中。如果这确实是一个问题,我的第一个选项将使用更少的内存,但我可选的第二个版本实际上是流式传输文件以避免任何内存负载。
  • @Miller True 但第二种解决方案需要订购文件。不确定这是否是一个问题,因为 OP 已接受此解决方案。
  • @jaypal 来自问题:“我的输入文件已排序。”但是,如果不是这种情况,我的解决方案都不会起作用。
【解决方案2】:

这是一个单一的班轮:

perl -ne 'chomp;if (/^([a-zA-Z]+)_/) { $hash{$1} .= ",$_"; } } END { for (keys %hash ) { print $_ . $hash{$_} . "\n" } ' input.txt

输入.txt:

XYZ_001
XYZ_005
XYZ_010
ABC_001
ABC_010

输出:

ABC,ABC_001,ABC_010
XYZ,XYZ_001,XYZ_005,XYZ_010

【讨论】:

    【解决方案3】:

    您可以尝试这种方法,它将您的 id 和值存储在数组哈希中,然后遍历它们并打印:

    use warnings;
    use strict;
    
    open my $in, '<', 'in.txt';
    
    my %data;
    my (@group, @n);
    while (<$in>){
        chomp;
        my @split = split(/_/);
        push @group, $split[0];
        push @n, $split[1];
    }
    
    push @{$data{$group[$_]} }, [ $n[$_] ] for 0 .. $#group;
    
    
    for my $group (reverse sort keys %data){
        for my $vals (@ {$data{$group} }) {
            my ($number) = @$vals; 
            print "$group\_$number,";
            }
            print "\n";
    }
    

    XYZ_001,XYZ_005,XYZ_010,
    ABC_001,ABC_010,
    

    【讨论】:

      【解决方案4】:

      perl 在线:

      perl  -F"_" -ane 'chomp;$s{$F[0]}.=",$_";END{ for $i (keys %s){print $i.$s{$i}."\n";} }' FILE
      

      我使用 uniq 哈希

      【讨论】:

        【解决方案5】:

        这是我使用awk 的方法

        awk -F_ '{a[$1]=(a[$1]?a[$1]","$0:$0)} END {for (i in a) print i","a[i]}' file
        ABC,ABC_001,ABC_010
        XYZ,XYZ_001,XYZ_005,XYZ_010
        

        【讨论】:

          猜你喜欢
          • 2018-08-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-18
          • 2021-06-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多