以下文件是配对端fastq文件的两个配对,我想根据它们的长度分隔每个fastq。
mate1.fq
:
@SRR127.1
TGGTTATGATGTTTGTGTAGGAATAGAAATTTTGATTAAGATATTAGTGAAATTTGAATGTAGTTTATTTGGAAGTTATGGAGAGTTTATATTGTATTTATGTTTATTGTTGTAGATTTATATTTATGTGTATATATTAGTTTTTTTGTGT
+
ABAAAF4FFFFFGGGGGGFFGGFGHGFGHHHHHGGCFFGHHHHH5FDBED55DGGFEGFHHHGBHDDHHHFF3AB3FFG5CBGBEF5BD5DGFEGHFAGAFEDGHGFHHGHGEFFGFGGHFEGHHFHGBEBGHHHHGHBHHFHHGGFGHH2
@SRR127.2
TATGGTAAGAAAATTGAAAATTATAAAAAATGAAAAATGTTTATTTGATGATTTGAAAAATGATGAAATTATTGAAAAATGTGAAAAATGAGAAATGTATATTGTAGGATTTGGAATATGGTGAGATAAATGAAAATTATAGTAAATG
+
AABAA5@D4@5CFFCA55FFGGHDGFHFFCC45DGFA2FA5DD55AAAA55DDBDEDDBGGFF5BA5DDABF5D5B5FF1ADFB5EDGHFG5@BFBD55D5FFB@@5@GBGEFBGHHGB@DBBFHFBDG3B43FFH@FGFHH?FHHHH
mate2.fq
:
@SRR127.1
ACCTATAAAAAAACCATATCAATAACTATAAAATCTTTATAAAATCCCACCCAATTAAAAAAAAATAAATTAATACATATAAAACCTTAAACACATAAAACATAATCACATACTATATAAACAATTACTATCACTACTAAACACCTAATA
+
>AA?AF13B@D@1EFCGGGFFG3EBGHHHBB2FGHHGHGFDGHHDFEGFHGGGHG1FFF1GGCGGGBGHHHHHFHHHHFHEGGFHF0BD1FGHHAGEGHFHHHFGGFHHGHHHFHHGGFHBGHFED1FBGFGFHDGHGHFGG1GB0GFHH
@SRR127.2
CTATTTCTCATTTTTTTATAATTTTCAATTCTCTTACCATATTCCACATCCTACACTAAACATTTCTAAATTTTCCACCTTTTTCTATTTTTCTCACCATATTTCATATCCTAAAAAACATATTCCTCATTTACTATAATTTTCAATTATC
+
11>>AFFDFF3@FFF?EFFGFBGHFDFA33D2FF2GGHFE12DD221AF1F1E1BG1GGBFBGGEGHDAABGAGDFABGG1BBDF12A2@2BG@2@DEFFF2B2@2222BB2211FGEE/11@22B2>1B22F2>GBGBD22BGD2>2B22
我编写了以下代码来执行此操作,但我只对第二个文件(mate2.fq
)收到一个奇怪的错误,而它们都有151 bp的读取。
#!/usr/bin/perl
use strict;
use warnings;
my @fh;
my $file_name = $ARGV[0];
my $infile = $ARGV[1];
#convert every 4-line fastq to 1-line
open(FH, "cat '$infile' | awk '{printf \"%s%s\",\$0,(NR%4?FS:RS)}' | ");
while (<FH>) {
chomp;
my @line = split(/\s+/, $_);
my $len = length($line[1]);
if ($len >= 100) {
#print $len,"\n",$_,"\n";
push @fh, $len;
if (not defined $fh[$len]) {
open $fh[$len], '>', "$file_name\_$len";
}
print { $fh[$len] } (join("\n", @line), "\n");
}
}
错误:
Can't use string ("151") as a symbol ref while "strict refs" in use at
如何处理这些文件?
答案 0 :(得分:6)
正如您所读到的,您的问题是由于虚假的push
在@fh
数组的末尾添加了一个整数值。我认为你的目标是扩展数组足够长以添加新的文件句柄。您可以通过分配到$#fh
来执行此操作,因此您可以编写$#fh = $len if $#fh < $len
;但是这是不必要的,因为Perl会在您简单地分配到数组末尾的元素时自动为您扩展数组
我对您的计划有一些评论,希望您找到有用的
发出awk命令是不必要和浪费的。 Perl完全有能力完成awk所能做的一切
如果您发现自己正在撰写split /\s+/, $_
,那么您几乎肯定只是split
:默认行为是split ' ', $_
。如果您使用/\s+/
作为模式,并且恰好在您要拆分的字符串上有前导空格,那么split
将返回一个空字符串作为字段列表中的第一项。如果您改为使用' '
(文字单个空格,而不是模式/ /
),那么这不会发生。实际上,split ' '
相当于/\S+/g
在字符串中插入变量值时,如果存在可能属于标识符的后续字符,则通常更适合将标识符放在大括号内。所以"${file_name}_$len"
代替"$file_name\_$len"
这就是我编写代码的方式。它将输入记录累积到$line
,直到添加了四个记录,然后像以前一样处理该行。
#!/usr/bin/perl
use strict;
use warnings;
my ($file_name, $infile) = @ARGV;
open my $in_fh, '<', $infile or die $!;
my $line;
my @fh;
while ( <$in_fh> ) {
chomp;
$line .= $_;
if ( $. % 4 == 0 or eof ) {
my @line = split ' ', $line;
my $len = length $line[1];
next if $len < 100;
open $fh[$len], '>', "${file_name}_$len" unless $fh[$len];
print { $fh[$len] } "$_\n" for @line;
$line = undef;
}
}
答案 1 :(得分:5)
这个错误具体意味着你正在做一些需要引用的东西,但它没有得到一个。
该行:
print {$fh[$len]} (join("\n",@line),"\n");
显式打印到文件句柄 - 看起来像名为@fh
的文件句柄列表。
这一行:
push @fh, $len;
将数值插入该列表。 (据推测$line[1]
长度为151个字符)。所以你真的想:
print {151} (join("\n",@line),"\n");
希望这很明显 - 只是不会起作用。您看起来像是在尝试打开文件句柄,并将其插入到数组中:
open $fh[$len], '>', "$file_name\_$len";
我可以建议您使用散列更好吗?否则你有一个充满空元素的数组,其中一个已填充。
你可以改为:
#further up:
my %fh;
#and then
open ( $fh{$len}, ">", "$file_name\_$len" ) or warn $!;
不要忘记在最后关闭文件句柄:
foreach my $key ( keys %fh ) {
close ( $fh{$key} );
}
我也建议而不是:
open( FH, "cat '$infile' | awk '{printf \"%s%s\",\$0,(NR%4?FS:RS)}' | " );
你可能最好在perl中处理它,因为你所做的只是使用外部二进制文件解析文件。 (并使用词汇文件句柄:`open($ input,“ - |,”cat'$ infile'| awk'{printf \“%s%s \”,\ $ 0,(NR%4?FS:RS)}' “)或警告$!;)