2011-11-25 74 views
4

我有一個我需要解析的字符串。它符合以下要求:Perl解析帶有一個或多個字段的字符串

  • 它由0個或多個鍵 - >值對組成。
  • 關鍵總是2個字母。
  • 該值是一個或多個數字。
  • 鍵和值之間不會有空格。
  • 單個對之間可能有或沒有空格。

例字符串予可能會看到:

  • AB1234 //一個鍵 - >值對(密鑰= AB,值= 1234)
  • AB1234 BC2345 //兩個鍵 - >值對,由空格分隔
  • AB1234BC2345 //兩個鍵 - >值對,而不是由空格分隔
  • //空斯汀,無鍵 - >值對
  • AB12345601BC1234CD1232PE2343 //許多鍵 - >值對,沒有空間
  • AB12345601 BC1234 CD1232 PE2343 //地段鍵 - >值對,用空格

我需要建立此字符串的一個Perl的哈希值。如果我能保證這是1對,我會做這樣的事情:

$string =~ /([A-Z][A-Z])([0-9]+)/ 
$key = $1 
$value = $2 
$hash{$key} = $value 

多個字符串,我可能會做在上述正則表達式的每場比賽後,我把原來的字符串的子事(豁免第一場比賽),然後再次搜索。不過,我確信有一個更聰明,更具風格的方式來實現這一點。

祝我沒有這樣一個糟糕的數據源來處理─

喬納森

+0

另請參見[如何將正則表達式捕獲存儲在Perl數組中?](http://stackoverflow.com/questions/2304577/)。 – outis

回答

8

與全局標誌列表環境,一個正則表達式將返回all matched substrings

use Data::Dumper; 

@strs = (
    'AB1234', 
    'AB1234 BC2345', 
    'AB1234BC2345', 
    '', 
    'AB12345601BC1234CD1232PE2343', 
    'AB12345601 BC1234 CD1232 PE2343' 
); 

for $str (@strs) { 
    # The money line 
    %parts = ($str =~ /([A-Z][A-Z])(\d+)/g); 

    print Dumper(\%parts); 
} 

要獲得更大的不透明度,請刪除模式匹配周圍的括號:%parts = $str =~ /([A-Z][A-Z])(\d+)/g;

3

你已經在那裏了:

$hash{$1} = $2 while $string =~ /([[:alpha:]]{2})([0-9]+)/g 
0

假設你的字符串肯定會符合您的方案(即不會有形式A122ABC123的任何字符串),那麼這應該工作:

my @strings = ('AB1234', 'AB1234 BC2345', 'AB1234BC2345'); 

foreach my $string (@strings) { 
    $string =~ s/\s+//g; 
    my ($first, %elems) = split(/([A-Z]{2})/, $string); 
    while (my ($key,$value) = each %elems) { 
     delete $elems{$key} unless $key =~ /^[A-Z]{2}$/; 
     delete $elems{$key} unless $value =~ /^\d{4}$/; 
    } 
    print Dumper \%elems; 
} 
+0

純正規表達式的答案看起來更清潔一些。我只是想用'split'來嘗試一些不同的東西。 :-) – CanSpice

+0

如果一切都在一個字符串中,你可以像'$ string =〜s/\ s + // g;我的%H =地圖{分流/(= \ d?)/(<= \ d?)}分流/(= \ d?)/,$字符串(<= \ d);' – flesk

+0

或者乾脆'%H = split/\ s *(\ d +)\ s * /,$ string' – TLP