2011-03-24 70 views
1

我讀從文件的字符串:Perl正則表達式問題!

2343,0,1,0 ... 500次...... 3

以上是$_一個例子,當它從讀一份文件。它是任何數目,接着500逗號分隔的0/1的然後我使用chop從字符串的末尾得到的數量3的數量3.

while(<FILE>){ 
    my $string = $_; 
    chomp($string); 
    my $a = chop($string); 
    my $found; 
    if($string=~m/^[0-9]*\,((0,|1,){$i})/){   
     $found = $&.$a; 
     print OTH $found,"\n"; 
     } 
} 

。然後匹配第一個數字,然後出現$i,出現0或1.我遇到的問題是chop由於某種原因無法處理字符串。在if聲明中,當我嘗試連接匹配和切碎的數字時,所有返回的內容都是$&的內容。

我也嘗試使用my $a = substr $a,-1,1;獲得數字3,這也沒有奏效。

奇怪的是,這段代碼在Windows上的Eclipse中工作,當我將它放到Linux服務器上時,它不起作用。任何人都可以發現我正在犯的愚蠢錯誤嗎?

+1

變量$ a和$ b在排序例程使用Perl的特殊變量;作爲一項規則,他們不應該在此之外使用。 – 2011-03-24 14:56:42

+0

不要使用[chop](http://perldoc.perl.org/functions/chop.html「perldoc -f chop」),它不是爲了這個。 – 2011-03-24 15:03:45

+0

請勿使用['$&'](http://perldoc.perl.org/perlvar.html#%24%26「perldoc -v $&」)。在程序的任何地方**使用這個變量**會對**所有**正則表達式匹配造成相當大的性能損失。 – 2011-03-24 15:36:58

回答

2

通常,我傾向於在數據中允許看不見的空白。我發現它使我的代碼更健壯,期望有人在行或字符串的末尾沒有看到額外的空間(如寫入日誌)。所以,我認爲這將解決您的問題:

my ($a) = $string =~ /(\S)\s*$/; 

當然,因爲你知道你正在尋找一些,它的更好更精確:

my ($a) = $string =~ /(\d+)\s*$/; 
+0

非常感謝,雖然其他答案提出了很好的觀點,但這正是問題所在。我認爲chomp()可以擺脫\ n和尾部空白,但我錯了。這是問題!我記得這個規則! – 2011-03-24 15:11:02

+0

@B。鮑爾斯,這是一個規則,這些年來爲許多很多解析器服務:忽略空白。 (對Python沒有大滿貫)。正則表達式使用lexing技術來創建臨時令牌。如果用戶在數據中有*任何*手:忽略 - 並允許 - 空格。 – Axeman 2011-03-24 16:36:59

1

照顧行尾字符...我不能在這裏測試,但我認爲你只是砍一個換行符。首先嚐試修剪你的字符串,然後將其切下。例如,請參閱http://www.somacon.com/p114.php

+0

chomp()應該吃掉所有的尾隨空格。 – 2011-03-24 14:36:15

+0

是的,如果正在讀取的數據在行尾有「\ r \ n」,則會發生這種情況。而不是'chomp'嘗試'Text :: Trim :: rtrim($ string)'或'$ string =〜s/\ s + $ //' – mkb 2011-03-24 14:37:38

+0

@West Hardaker - chomp只會刪除與$/' – mkb 2011-03-24 14:38:25

1

而不是試圖這樣做,爲什麼不使用正則表達式來一次性提取所需的一切?

my $x = "4123,0,1,0,1,4"; 
$x =~ /^[0-9]+,((?:0,|1,){4})([0-9]+)/; 
print "$1\n$2\n"; 

產地:

0,1,0,1, 
4 

,這是相當多的,你在找什麼。兩組需要的答案都在匹配變量中。

請注意,我包括?:在前面的0,1,因此它的沒有結尾在輸出匹配變量。

0

我真的不是確定你想在這裏實現什麼,但我已經嘗試了Win32和Solaris上的代碼,並且它工作正常。你確定$我是正確的號碼嗎?可能更容易使用*或?

use strict; 
use warnings; 

while(<DATA>){ 
    my $string = $_; 
    chomp($string); 
    my $a = chop($string); 
    print "$string\n"; 
    my $found; 
    if($string=~m/^[0-9]*\,((0,|1,)*)/){   
     $found = $&.$a; 
     print $found,"\n"; 
     } 
} 



__DATA__ 
2343,0,1,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,3 
0

我看不出有任何理由使用正則表達式在這種情況下,只需使用split

use strict; 
use warnings; 
use autodie; # open will now die on failure 

my %data; 

{ 
    # limit the scope of $fh 
    open my $fh, '<', 'test.data'; 
    while(<$fh>){ 
    chomp; 
    s(\s+){}g; # remove all spaces 

    my($number,@bin) = split ',', $_; 
    # uncomment if you want to throw away the 3 
    # pop @bin if $bin[-1] == 3; 
    $data{$number} = \@bin; 
    } 
    close $fh; 
} 

如果你想要的是3

while(<$fh>){ 
    # the .* forces it to look for the last set of numbers 
    my($last_number) = /.*([0-9]+)/; 
}