2016-06-29 18 views
2

我正在解析製表符分隔的文件。即使數字明確,也不會將數列識別爲數字。當我嘗試總結這些值時顯示錯誤: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"; 
} 
+4

' 「97」'確實不像一些,不像'97'。這聽起來像你的領域裏有引號。 – melpomene

回答

6

你的錯誤信息已經說明了:論證 「」 97 「」 不是數字。這種情況發生在實際上是一個字符串其用引號括起來("),像這樣:

my $num = '"42"'; 
my $sum = $num + 1; 

這給:

論證 「」 42 「」 不除...以外的數字(+)...

試圖從你的擺脫報價:

$num =~ s/"//g; 
+1

作爲一種選擇 - 模式匹配數字組件:'my($ num)= $ str =〜m /(\ d +)/;' – Sobrique

+0

@Sobrique好得多。像我所做的那樣剝離引號是quick'n'drty大錘的方法。 – PerlDuck

4

注意  建議使用Text::CSV來(還)處理額外的報價是在最後


該錯誤是由於額外的引號,但我首先會提到一個編碼問題。通過做looks_like_number($var) + ...添加值是一個錯誤。如果perl的認爲EXPR是一個數字 的looks_like_number,從Scalar::Util

返回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; 

這裏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. double 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; 
+1

@ user3781528你確實得到了直接的答案,這很好,但我認爲你應該看看這裏的更新,就這樣。 – zdim