【问题标题】:Perl: removing unique lines between two filesPerl:删除两个文件之间的唯一行
【发布时间】:2016-09-02 02:21:14
【问题描述】:

我感兴趣的是删除两个文件之间的唯一行,而不是删除重复的行。这些文件有不同的格式。

文件 1:

m160505_031746_42156_s1_p0|105337|10450_16161
m160505_031746_42156_s1_p0|104750|20537_27903
m160505_031746_42156_s1_p0|103809|17563_25308
m160505_031746_42156_s1_p0|103217|8075_11486 

文件 2(制表符分隔):

acCAATCCCATCACCATCtt    m160505_031746_42156_s1_p0|105337|10450_16161
atTAAAATACCATTATATgg    m160505_031746_42156_s1_p0|104750|20537_27903
caAACTCCAACTACGAACtg    m160505_031746_42156_s1_p0|103809|17563_25308
atCTATTTAAACCTAATCgg    m160505_031746_42156_s1_p0|103217|8075_11486
acCAATCCCATCACCATCtt    m160505_031746_42156_s1_p0|152092|36592_40830
atTAAAATACCATTATATgg    m160505_031746_42156_s1_p0|143825|13009_23809
caAACTCCAACTACGAACtg    m160505_031746_42156_s1_p0|143710|0_20191
atCTATTTAAACCTAATCgg    m160505_031746_42156_s1_p0|140833|25358_34709

文件 2 与第 2 列中的文件 1 具有相同的行,在第 1 列中以 20 个字母开头。第 1 列中的 20 个字母模式在文件 2 中重复(多次,不仅仅是两次),具有唯一的关联序列每次出现。

我想将文件 1 中的序列与文件 2 中的第二列进行匹配。如果有匹配项,我想为每个匹配项生成一个包含两列的新文件,保持文件 2 之间的关系两列。实际上,我希望简单地删除文件 2 中与文件 1 中的第 2 列不匹配的行。

我意识到我的代码需要帮助,但到目前为止,我所提供的信息可以让您更多地了解我的想法。我可能最终需要使用哈希,尽管我担心这样做是因为第 1 列中的重复。我不想丢失这些以及它们与第 2 列的关系。

use strict;
use warnings;

open(OUT, '>', '/path/to/out.txt') or die $!;
open(FMT0, '<', '/path/to/fmt0.txt') or die $!;

my $regex = qr/m160505_.*/;
while(my $line = <FMT0>){
    $line =~ $regex;
    open(FMT6, '<', '/path/to/fmt6.txt') or die $!;
    while(my $zero_fmt = <FMT6>){
            if ($zero_fmt =~ /([A-Z]{20})\t($line)/i){
                    print OUT $zero_fmt;
            }
    }
}

感谢您的帮助!

【问题讨论】:

  • @Sebastian Lenartowicz 感谢您帮我解决了一些问题。

标签: regex perl


【解决方案1】:

这样的事情可能会完成工作。 :-)

grep -f <(grep ^m160505_ file1) file2

这是一个 Perl 解决方案,因为这就是您所要求的:

#!/usr/bin/env perl

use strict;
use warnings;

die "usage: $0 <file1> <file2>\n"
  unless @ARGV == 2;

open(my $file1, '<', $ARGV[0])
  or die "Could not open file1: $!\n";

my %keys;
while (<$file1>) {
  chomp;
  $keys{$_} = 1 if /^m160505_/;
}

close($file1);

open (my $file2, '<', $ARGV[1])
  or die "Could not open file2: $!\n";

while (<$file2>) {
  chomp;
  my ($key) = /\t(.+)$/;
  print "$_\n" if $keys{$key};
}

close($file2);

在行动:

$ grep -f <(grep ^m160505_ file1) file2
acCAATCCCATCACCATCtt    m160505_031746_42156_s1_p0|105337|10450_16161
atTAAAATACCATTATATgg    m160505_031746_42156_s1_p0|104750|20537_27903
caAACTCCAACTACGAACtg    m160505_031746_42156_s1_p0|103809|17563_25308
atCTATTTAAACCTAATCgg    m160505_031746_42156_s1_p0|103217|8075_11486

$ ./atgc.pl file1 file2
acCAATCCCATCACCATCtt    m160505_031746_42156_s1_p0|105337|10450_16161
atTAAAATACCATTATATgg    m160505_031746_42156_s1_p0|104750|20537_27903
caAACTCCAACTACGAACtg    m160505_031746_42156_s1_p0|103809|17563_25308
atCTATTTAAACCTAATCgg    m160505_031746_42156_s1_p0|103217|8075_11486

【讨论】:

  • 太棒了!谢谢。您对 grep 的看法是正确的,但我非常感谢您对此的 perl 回答。很多人想要删除重复的行,而不是唯一的行。我很难回答这个问题。你让它看起来很容易! :)
  • 在一个文件中查找与另一个文件中的行匹配的行在某种程度上是一个常见的 Unix 命令行任务,所以一旦您看过几次,解决方案就很自然了!乐于助人。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
  • 2013-06-19
相关资源
最近更新 更多