合并列,但它在perl代码中进入新行

问题描述

我对Perl代码非常陌生,并且正在将一些数据集与以下代码合并。数据是这样设置的:第一行指定样品名称,然后第二,第三列上的计数...。第一列指定基因名称。我已经合并了2个大数据集,并且我一直在使用以下Perl脚本,方法是指定perl脚本的路径,并在Terminal中运行以下代码

$ cd /path/to/file
$ perl /path/to/file dataset1.txt dataset2.txt merged.txt

Perl脚本如下:

use strict;
my $file1=$ARGV[0];              
my $file2=$ARGV[1];             
my $out=$ARGV[2];               
my %hash=();                     

open(RF,"$file1") or die $!;    
while(my $line=<RF>){
  chomp($line);
  my @arr=split(/\t/,$line);
  my $gene=shift(@arr);
  $hash{$gene}=join("\t",@arr);
}
close(RF);

open(RF,"$file2") or die $!;     
open(WF,">$out") or die $!;    
while(my $line=<RF>){
  chomp($line);
  my @arr=split(/\t/,$line);
  my $gene=shift(@arr);
  if(exists $hash{$gene}){
    print WF $gene . "\t" . $hash{$gene} . "\t" . join("\t",@arr) . "\n";
  }
}
close(WF);
close(RF);

使用上面的代码,我应该得到一个合并表,删除重复的行,并将第二个文本文件的(样本A到样本Z)列合并到第一个文本文件的列(样本1到样本100) ,因此应看起来像这样,以制表符分隔。

Gene Name Sample 1 Sample 2 ..... Sample A Sample B...
TP53      2.345    2.234          4.32     4.53

当合并的文件又合并了两个数据集时返回问题,但是第二个数据集在下一行而不是同一行。它将识别,排序和合并计数,但移至下一行。我的代码或输入内容有问题吗?

感谢您的所有帮助!

解决方法

双行问题可能是由于输入文件中有外来行结尾。您可以使用以下命令检查此内容:

$ perl -MData::Dumper -ne'$Data::Dumper::Useqq=1; print Dumper $_' file1.txt

您的代码还有更多问题,如下所示。

您似乎正在做的事情是根据第1列中的名称连接行。您应该注意,此匹配区分大小写,因此可以区分例如tp53和{{1} }或TP53Gene name,或与Gene NameTP53一样微妙的东西(多余的空格)。那可以是好事也可以是坏事,但是要为极端情况做好准备。

您期望程序,输入文件和输出有3个参数,但这是一种不完善的方式。我将使用Diamond运算符来输入文件,然后使用shell命令重定向输出,例如:

TP53 

例如,这将为您提供添加更多文件进行合并的灵活性,并使您可以选择在不提交文件的情况下测试合并。

您正在使用2个参数$ perl foo.pl file1 file2 > merged.txt 命令,但未指定打开模式(例如open)。那是非常危险的,并且使您容易进行代码注入。例如,某人可以输入"<"作为程序的第一个参数,然后删除整个硬盘(或允许的权限)。为防止这种情况,请使用3参数打开并指定硬编码打开模式。

Perl中的打开命令还应使用词汇文件句柄,例如"| rm -rf /",而不是全局的。它应该看起来像这样:

my $fh

但是由于我们使用的是菱形运算符,因此Perl会自动为我们处理。

您也不需要将文件的读取分为两个循环,因为您基本上在做相同的事情。也无需先拆分线,然后再将它们重新连接在一起。

我将其写为一个如何完成的示例:

open my $fh,"<",$input1 or die $!;
open my $fh_out,">",$output or die $!;

在我的系统上,它提供输出:

use strict;
use warnings;

my %data;
while (<DATA>) {
    chomp;
    my ($name,$line) = /^([^\t]+)(.+)/;    # using a regex match avoiding split
    $data{$name} .= $line;                  # merge lines using concatenation
}

for my $name (sort keys %data) {
    print $name . $data{$name} . "\n";
}

__DATA__
Gene Name   Sample 1    Sample 2    Sample 3    Sample 4
TP53    2.345   2.234   4.32    4.53
TP54    2.345   2.234   4.32    4.53
TP55    2.345   2.234   4.32    4.53
Gene Name   Sample A    Sample B    Sample C    Sample D
TP53    2.345   2.234   4.32    2.53
TP54    2.212   1.234   3.32    6.53
TP55    1.345   2.114   7.32    5.53

这将按字母顺序输出行。如果要保留文件的顺序,可以在读取文件时将其收集在数组中,并在打印时使用。数组保留顺序,哈希键不保留。