2012-11-20 23 views
1

我有以下代碼:的Perl的grep沒有返回預期值

#!/usr/bin/perl 
# splits.pl 

use strict; 
use warnings; 
use diagnostics; 

my $pivotfile = "myPath/Internal_Splits_Pivot.txt"; 

open PIVOTFILE, $pivotfile or die $!; 

while (<PIVOTFILE>) { # loop through each line in file 

    next if ($. == 1); # skip first line (contains business segment code) 
    next if ($. == 2); # skip second line (contains transaction amount text) 

    my @fields = split('\t',$_); # split fields for line into an array  

    print scalar(grep $_, @fields), "\n"; 

} 

鑑於在文本文件中的數據是這樣的:

4 G I M N U X 
    Transaction Amount Transaction Amount Transaction Amount Transaction Amount Transaction Amount Transaction Amount Transaction Amount 
0000-13-I21    600   
0001-8V-034BLA    2,172 2,172  
0001-8V-191GYG     13,125  4,375 
0001-9W-GH5B2A -2,967.09  2,967.09 25.00   

我期望從Perl腳本的輸出爲:2 3 3 4給出每行中定義元素的數量。該文件是一個帶有8列的製表符分隔的文本文件。

相反,我得到3 4 3 4,我不知道爲什麼!

對於背景,我使用Counting array elements in Perl作爲我開發的基礎,因爲我正在計數行中元素的數量,以瞭解是否需要跳過該行。

回答

1

您的代碼works for me。問題可能在於輸入文件包含一些「隱藏的」空白字段(例如,除tab之外的其他空白字符)。例如

  • A<tab><space><CR>給出了兩個領域,A<space><CR>
  • A<tab>B<tab><CR>給出了三個,AB<CR>(記住,行的結尾是輸入的一部分!)

我建議你到chomp你使用的每一行;除此之外,你將不得不從只有空白的字段中清理數組。例如。

scalar(grep /\S/, @fields) 

應該這樣做。

+0

+1幫助我記住'chomp'!也爲提供答案:) –

+0

改變我的答案,因爲最終這是最能幫助我的! :)我發佈了一個答案,下面的解決方案爲我工作。 –

2

的問題應該是在這一行:

my @fields = split('\t',$_); # split fields for line into an array 

製表符沒有得到插值。而你的文件似乎不是製表符分隔的,至少在這裏是分開的。我改變了拆分正則表達式匹配任意空白,跑到我的機器上的代碼,並得到了「正確」的結果:

my @fields = split(/\s+/,$_); # split fields for line into an array 

結果:

2 
3 
3 
4 
+0

感謝您的幫助,但沒有骰子。我做了改變,仍然有相同的結果。 –

+1

用'「\ t'',因爲'」「'沒有解釋,除了''\\和反斜線\」,傳遞給正則表達式編譯字符串實際上是一個反斜槓和T,但正則表達式編譯器本身手柄反斜槓並正確生成一個標籤正則表達式。但是你是正確的,/ \ t /是更好的形式。 – ysth

+0

@ScottHoltzman看到我的編輯,現在應該工作! :) – memowe

2

我懷疑你有空間與標籤混合一些地方,你的grep測試會考慮「」真實。

是什麼:

use Data::Dumper; 
$Data::Dumper::Useqq=1; 
print Dumper [<PIVOTFILE>]; 

說明了什麼?

+0

+1爲顯示OP調試他的數據結構的一個好方法 – memowe

+0

我第二個+1。自從我寫perl之後已經有一段時間了,我忘記了這個寶貴的資源。 –

2

不僅有標籤,但也有空格。

的空間嘗試與拆分工作 看看下面

#!/usr/bin/perl 
# splits.pl 

use strict; 
use warnings; 
use diagnostics; 



while (<DATA>) { # loop through each line in file 

    next if ($. == 1); # skip first line (contains business segment code) 
    next if ($. == 2); # skip second line (contains transaction amount text) 


    my @fields = split(" ",$_); # split fields by SPACE  

    print scalar(@fields), "\n"; 

} 

__DATA__ 
    4 G I M N U X 
    Transaction Amount Transaction Amount Transaction Amount Transaction Amount Transaction Amount Transaction Amount Transaction Amount 
0000-13-I21    600   
0001-8V-034BLA    2,172 2,172  
0001-8V-191GYG     13,125  4,375 
0001-9W-GH5B2A -2,967.09  2,967.09 25.00 

輸出

2 
3 
3 
4 
+0

確實必須是原始數據中的選項卡,否則報告的結果不會發生。 – ysth

+0

+1謝謝!由於這是第一篇關於我的問題的文章,我將其標記爲答案。問題在於額外的空間,並改變了拆分,以空間分割! –

+0

'split(「」,$ _)'最好寫成'split' – Borodin

2

補充說明:

有關背景,我使用Counting array elements in Perl爲我發展的基礎,因爲我想算在該行的元素個數知道如果我需要跳過還是不行。

現在我明白爲什麼你用grep計算數組元素。這一點很重要,當你的數組包含未定義的值喜歡這裏:

my @a; 
$a[1] = 42;  # @a contains the list (undef, 42) 
say scalar @a; # 2 

,或當你手動刪除的條目:

my @a = split /,/ => 'foo,bar'; # @a contains the list ('foo', 'bar') 
delete $a[0];      # @a contains the list (undef, 'bar') 
say scalar @a;      # 2 

但在許多情況下,特別是當你使用數組只是存儲列表不工作在單個陣列元素上,scalar @a作品完美細緻

my @a = (1 .. 17, 1 .. 25);  # (1, 2, ..., 17, 1, 2, .., 25) 
say scalar @a;      # 42 

重要的是要明白,grep做什麼!在你的情況

print scalar(grep $_, @fields), "\n"; 

grep返回的@fields真正值列表,然後打印你有多少。但有時這是不是你想要/期望:

my @things = (17, 42, 'foo', '', 0); # even '' and 0 are things 
say scalar grep $_ => @things   # 3! 

因爲空字符串和數字0是在Perl假值,也無法獲得與成語計數。所以,如果你想知道如何長的陣列,只需使用

say scalar @array; # number of array entries 

如果你想數真正值,使用此

say scalar grep $_ => @array; # number of true values 

但是,如果你想計算定義值,使用這個

say scalar grep defined($_) => @array; # number of defined values 

我敢肯定,你已經知道這從鏈接頁面上的其他答案。在哈希值,這種情況是有點更復雜,因爲設置的東西undef是不一樣的delete荷蘭國際集團它:

my %h = (a => 0, b => 42, c => 17, d => 666); 
$h{c} = undef; # still there, but undefined 
delete $h{d}; # BAM! $h{d} is gone! 

會發生什麼事,當我們試圖算值?

say scalar grep $_ => values %h; # 1 

因爲42處於%h唯一值。

say scalar grep defined $_ => values %h; # 2 

因爲0被定義,儘管它是錯誤的。

say scalar grep exists $h{$_} => qw(a b c d); # 3 

因爲未定義的值可以存在。結論:

知道你在做的,而不是copy'n'pasting代碼片段是什麼:)

+0

+ +1努力寫出這個令人難以置信的解釋。 –

0

在這個問題上有很多很大的幫助,並迅速呢!

一個長期的,曠日持久的學習過程後,這是我想出了相當奏效,與預期的結果。

#!/usr/bin/perl 
# splits.pl 

use strict; 
use warnings; 
use diagnostics; 

my $pivotfile = "myPath/Internal_Splits_Pivot.txt"; 

open PIVOTFILE, $pivotfile or die $!; 

while (<PIVOTFILE>) { # loop through each line in file 

    next if ($. == 1); # skip first line (contains business segment code) 
    next if ($. == 2); # skip second line (contains transaction amount text) 

    chomp $_; # clean line of trailing \n and white space 

    my @fields = split(/\t/,$_); # split fields for line into an array  

    print scalar(grep $_, @fields), "\n"; 

} 
+0

因此,您仍然只需要計算* true *值? :) – memowe

+1

@memowe - >是的,我只想在我正在使用的邏輯中使用真值。不過,我確實感謝你提出了這個出色的解釋。這非常明確,幫助我理解了所有的概念,而不僅僅是我與之合作的原始鏈接。 SO用戶的慷慨讓我驚歎不已! –