perl脚本读取文件并将每行与前一行进行比较

时间:2014-05-02 19:54:07

标签: perl

我有一个看起来像的文件:

chr start end fold_enrichment  
1 760605 769233 15.65  
1 760605 769233 44.11  
1 760605 769233 18.5  
1 760605 769233 11.38  
1 947714 951356 110.99  
1 1404923 1410311 96.76  
1 1404923 1410311 27.04  

我想编写一个逐行遍历文件的perl脚本,并将每行与前一行(或下一行)进行比较,以查找前3列中的匹配值。然后我想只在前三列打印一次值,第四列值作为新列推送。

例如,我想采取

1 760605 769233 15.65  
1 760605 769233 44.11  
1 760605 769233 18.5  

并打印

1 760605 769233 15.65 44.11 18.5

谢谢!

3 个答案:

答案 0 :(得分:2)

perl -ape '$k="@F[0..2]"; $_=" $F[3]",next if $k eq $o; $_= "\n@F";$o=$k' file

输出

1 760605 769233 15.65 44.11 18.5 11.38
1 947714 951356 110.99
1 1404923 1410311 96.76 27.04

答案 1 :(得分:1)

正如鲍罗丁所说,SO不是免费服务。请始终展示您的工作并解释您遇到问题的地方。

然而,是的,偶尔我们中的一些人会因为它的乐趣而更加慷慨。 perl one-liner:

perl -0777 -pe "1 while (s/^(\S+\s+\S+\s+\S+) (.*?)\s*\n\1 (.*)/$1 $2 $3/mg)" data.txt

输出:

chr start end fold_enrichment
1 760605 769233 15.65 44.11 18.5 11.38
1 947714 951356 110.99
1 1404923 1410311 96.76 27.04

答案 2 :(得分:1)

以下是我对单行的尝试:

perl -lane '$k="@F[0..2]"; push @o,$k if !$h{$k}; push @{$h{$k}},$F[3] }{ print "$_ @{$h{$_}}" for @o' file

输出

chr start end fold_enrichment
1 760605 769233 15.65 44.11 18.5 11.38
1 947714 951356 110.99
1 1404923 1410311 96.76 27.04

<强>阐释:

  • -a选项将行拆分为字段。
  • -l选项为我们选择并在打印期间放回新行
  • -n选项对文件的每一行执行
  • -e选项告诉perl执行代码块
  • $k = "@F[0..2]"创建一个变量$k,其中包含当前行的前三个字段
  • push @o, $k if !$h{$k}只有在我们的哈希中不存在时才会创建一个数组并将变量推送给它。这是为了防止插入重复。这也是为了我们可以保留订单
  • push @{$h{$k}}, $F[3]我们正在创建数组哈希。使用键作为$k并将值作为最后一个字段推送到哈希。
  • }{表示END
  • print "$_ @{$h{$_}}" for @o打印数组@o的每个元素的键和值。

以下是更易读的单行内容:

perl -lane '{
    $k = "@F[0..2]";  
    push @o, $k if !$h{$k}; 
    push @{$h{$k}}, $F[3]
}
END { 
    print "$_ @{$h{$_}}" for @o
}' file