使用来自不同文件的值打印哈希值

时间:2016-12-04 19:48:14

标签: perl hash printing

我想创建包含文件1和文件2的值的输出文件。

文件1中的行:

  

chr1袖扣外显子708356 708487 1000 - 。
  gene_id" CUFF.3&#34 ;; transcript_id" CUFF.3.1&#34 ;; exon_number" 5&#34 ;; FPKM   " 3.1300591420&#34 ;; frac" 1.000000&#34 ;; conf_lo" 2.502470&#34 ;; conf_hi   " 3.757648&#34 ;; cov" 7.589085&#34 ;; chr1Cufflinks外显子708356   708487 - 。 gene_id" XLOC_001284&#34 ;; transcript_id   " TCONS_00007667&#34 ;; exon_number" 7&#34 ;; gene_name" LOC100288069&#34 ;; OID   " CUFF.15.2&#34 ;; nearest_ref" NR_033908&#34 ;; class_code" j&#34 ;; tss_id   " TSS2981&#34 ;;

文件2中的一行:

  

CUFF.48557
  CHR4:160253850-160259462:160259621-160260265:160260507-160262715

此文件的第二列是唯一ID(uniq_id)。

我想以下列格式获取输出文件: transcript_id(CUFF_id)uniq_id gene_id(XLOC_ID)FPKM

我的脚本从第一个文件中获取XLOC_ID和FPKM值,并将它们与第二个文件中的两列一起打印出来。

record 1 --> 40 min --> record 2 --> 50 min --> record 3

我在文件外部初始化了哈希值,但是每个CUFF值都出现以下错误:

  

CUFF.24093
  chr17:3533641-3539345:3527526-3533498:3526786-3527341:3524707-3526632

     

在连接(。)中使用未初始化的值或在ex_1.pl中使用字符串   第55行,第9343行。

     

在连接(。)中使用未初始化的值或在ex_1.pl中使用字符串   第55行,第9343行。

如何解决此问题?

谢谢!

1 个答案:

答案 0 :(得分:1)

我认为警告消息是因为$id键,(CUFF.24093),您上传第二个文件的9343并未包含在您创建的哈希中在第一个文件中。

第二个文件中的ID是否可能不包含在第一个文件中?这似乎就是这种情况。

如果是这样,并且您只想跳过此未知ID,则可以在程序中添加一行,如:

my $id = $array[0];
my $uniq = $array[1];

next unless exists $fpkm_hash{$id}; # add this line

print $id . "\t" . $uniq . "\t" . $xloc_hash{$id} . "\t" . $fpkm_hash{$id} . "\n";

这将绕过以下print语句并返回while循环的顶部,并在下一行中读取并继续处理。

这取决于您遇到未知ID时要采取的操作。

更新:我想我可能会对您的代码进行一些观察/改进。

my $v_merge_gtf = shift @ARGV or die $!;
my $unique_gtf = shift @ARGV or die $!;

错误变量$!在这里没有用处(这是我最近才发现的事实,即使在使用Perl 14年之后)。 $!仅设置为系统调用(您涉及操作系统)。最常见的是open并关闭文件,opendir和closedir用于目录。如果在打开/关闭文件或目录时发生错误,$!将包含错误消息。 (请参阅我在附带的代码中处理此问题的方法 - 如果$usage没有成功,我会创建一条消息,shift

我没有使用2个哈希来存储信息,而是使用了1个哈希%data。优点是它将使用更少的内存,(因为它只存储1组密钥而不是2组),但是,如果你愿意,你可以使用2。

我使用推荐的3个参数(filehandle, mode, filename)表单来打开文件。您使用的2参数方法已过时且安全性较低(原因我在此处未详细说明)。另外,我使用的词法文件句柄my $mrgmy $unique是创建文件句柄的新方法(而不是使用FILE进行2次打开)。

您可以直接在{while循环中$line分配while (my $line = <FILE>),而不是像$line那样。在我的示例程序中,我没有分配给$_,而是依赖于默认变量next unless /\S/; my @array = split /\t/;。 (它简化了以下两个语句chomp)。我没有chomp第一个文件,因为你只是在字符串中解析而不是使用字符串末尾的任何内容。while是必需的第二个my $uniq = ...循环,因为第二个变量chomp如果没有被if ($line =~ /[a-z]/)移除,则会在其末尾有换行符。

我不知道这句话的意思,next unless /\S/;。我假设您要检查空行并且只处理具有非空间数据的行。这就是我写my $id = $array[8];的原因。 (说要跳过以下语句并进入while循环的顶部并阅读下一条记录)。

您的第一个while循环有效,因为输入文件中没有错误。如果有错误,你编写代码的方式可能就是一个问题。

如果以下$id语句为false,则if语句会为$fpkm提供一个错误使用的值。 (对于您要捕获的其他2个变量,$xlocdie)也是如此。你可以在我的代码示例中看到我是如何处理这个的。

在我的代码中,如果匹配没有成功,我就死了,您可能不想match or next而是说$array[8] =~ /gene_id "(CUFF\S+)";/来尝试下一行数据。这取决于您希望如何处理失败的匹配。

在这一行";中,请注意我将or die "Could not find ID in $v_merge_gtf (line# $.)";放在捕获的数据之后,因此无需将其从捕获的数据中删除(就像您在替换中所做的那样)

嗯,我知道这是对您的代码的长篇评论,但我希望您能对我推荐更改的原因有所了解。

$.

#!/usr/bin/perl use warnings; use strict; my $usage = "USAGE: perl $0 merge_gtf_file unique_gtf_file\n"; my $v_merge_gtf = shift @ARGV or die $usage; my $unique_gtf = shift @ARGV or die $usage; my %data; open my $mrg, '<', $v_merge_gtf or die $!; while (<$mrg>) { next unless /\S/; my @array = split /\t/; if ($array[2] eq 'exon') { $array[8] =~ /gene_id "(CUFF\S+)";/ or die "Could not find ID in $v_merge_gtf (line# $.)"; my $id = $1; $array[8] =~ /FPKM "(\S+)";/ or die "Could not find FPKM in $v_merge_gtf (line# $.)"; my $fpkm = $1; $array[17] =~ /gene_id "(XLOC\S+)";/ or die "Could not find XLOC in $v_merge_gtf (line# $.)"; my $xloc = $1; $data{$id}{fpkm} = $fpkm; $data{$id}{xloc} = $xloc; } } close $mrg or die $!; open my $unique, '<', $unique_gtf or die $!; while (<$unique>) { next unless /\S/; chomp; my ($id, $uniq) = split /\t/; print join("\t", $id, $uniq, $data{$id}{fpkm}, $data{$id}{xloc}), "\n"; } close $unique or die $!; 是正在读取的文件的行号。

{{1}}