将字符串转换为数字"参数不是数字错误"

use*_*528 2 perl parsing

我正在解析制表符分隔文件.即使数字明显是数字,也有几列不被识别为数字.当我尝试总结这些值时,会显示错误: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";
}
Run Code Online (Sandbox Code Playgroud)

Per*_*uck 6

您的错误消息已经说明了:参数""97""不是数字.当数字实际上是一个被引号(")包围的字符串时会发生这种情况,如下所示:

my $num = '"42"';
my $sum = $num + 1;
Run Code Online (Sandbox Code Playgroud)

这给出了:

参数""42""除了(+)之外不是数字......

试着摆脱你的数字引用:

$num =~ s/"//g;
Run Code Online (Sandbox Code Playgroud)


zdi*_*dim 5

该错误是由于额外的引号引起的,但我首先要提到一个编码问题。这样做添加值looks_like_number($var) + ...是错误的。由Scalar :: Util提供looks_like_number

如果perl认为EXPR是一个数字,则返回true。

它用于测试变量是否为数字。它返回零或大的正整数。因此,您需要首先进行测试以查看哪些是数字,例如通过使用grep进行过滤,然后才将其用作数字。

正如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;
Run Code Online (Sandbox Code Playgroud)

这里sum从核心List :: Util模块开始使用。如果不执行求和操作,上述所有操作都可以在一个语句中进行,因为每个操作都返回并获取一个列表。


更好的是,您可以使用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;
Run Code Online (Sandbox Code Playgroud)