我正在解析制表符分隔文件。即使数字明显是数字,也有几列不被识别为数字。当我尝试总结这些值时,会显示错误:Argument ""97"" isn't numeric in addition (+)
,Perl返回0.
我尝试使用Scalar::Util qw(looks_like_number);
,但它产生了相同的结果' 0'。还有什么我可以尝试的吗?
以下是代码:
open my $out_fh, '>', $final_variants or die qq{Unable to open "$final_variants" for output: $!};
open my $in_fh, '<', $tsv_file_new
or die qq{Unable to open "$tsv_file_new" for input: $!};
while ( <$in_fh> ) {
my @fields = split;
my $forward_reference = $fields[67];
my $reverse_reference = $fields[68];
my $forward_variant_reads = $fields[77];
my $reverse_variant_reads = $fields[78];
my $total_reads = (looks_like_number($forward_reference))
+ (looks_like_number($reverse_reference))
+ (looks_like_number($forward_variant_reads))
+ (looks_like_number($reverse_variant_reads));
my $current_final_line = $headerline . "\t"
. $forward_reference . "\t"
. $reverse_reference . "\t"
. $forward_variant_reads . "\t"
. $reverse_variant_reads . "\t"
. $total_reads . "\t";
print $out_fh $current_final_line, "\n";
}
答案 0 :(得分:6)
您的错误消息已经说明了:参数“”97“”不是数字。当数字实际上是一个由引号("
),包围的字符串时会发生这种情况:
my $num = '"42"';
my $sum = $num + 1;
这给出了:
参数“”42“”在...(+)处不是数字......
尝试摆脱数字中的引号:
$num =~ s/"//g;
答案 1 :(得分:4)
该错误是由于额外的引号,但我首先提到了编码问题。通过执行looks_like_number($var) + ...
来添加值是一个错误。
来自looks_like_number的Scalar::Util,
如果perl认为EXPR是一个数字,则返回true。
用于测试变量是否为数字。它返回零或大的正整数。因此,您需要首先测试哪些是数字,例如通过grep过滤,然后才将它们用作数字。
正如answer by perlduck中所解释的那样,显然还有额外的引用。但是,我要小心只删除所有引号,因为你可能会暴露一些确实不是数字的东西。此外,如果涉及其他处理,则可能需要内部字符串中的可能引号。
我仍然会最终通过looks_like_number
测试变量,清理封闭的引号,并组装那些数字的变量。也许
use List::Util qw(sum);
# Remove extra (leading and trailing) quotes, for example
my @references = map { s/^"//; s/"$//; $_ } ($forward_reference, ...);
my @numeric_refs = grep { looks_like_number($_) } @references;
my $total_reads = sum @numeric_refs;
此处使用来自核心List::Util模块的sum
。如果除了求和之外什么都没有,那么上述所有内容都可以在一个语句中,因为每个操作都返回并获取一个列表。
更好的是,你可以使用Text::CSV解析制表符分隔的文件,它可以很好地处理引号。
use warnings;
use strict;
use Text::CSV;
use List::Util qw(sum);
my $csv = Text::CSV->new(
{ binary => 1, sep_char => "\t", allow_loose_quotes => 1 }
) or die "Cannot use CSV: " . Text::CSV->error_diag ();
my $file = $tsv_file_new;
open my $fh, '<', $file or die "Can't open $file: $!";
while (my $row = $csv->getline($fh)) {
my @fields = @$row;
# process. quotes around fields are gone
# ...
my @references = ($forward_reference, ...);
my $total_reads = sum grep { looks_like_number($_) } @references;
}
$csv->eof or $csv->error_diag();
close $fh;