2012-10-22 165 views
0

我有以下字符串:解析字符串轉換爲哈希結構在Perl

$str = "list 
    XYZ 

    status1 : YES 
    value1  : 100 
    status2  : NO 
    value2  : 200 
Thats all";  

我想用一個函數,它接受這個字符串作爲輸入,並返回與status1哈希把它轉換成一個散列例如,密鑰YES作爲

如何做?
以及如何引用返回的散列?

+0

問題不明確界限是什麼。我們應該假設冒號後面的第一個非空格標記是否爲值,而不是包含由冒號分隔的兩個標記的行上的東西應該被忽略? – tripleee

+0

關於引用返回散列的最後一個問題與解析問題無關,[很平凡](http://p3rl.org/perlreftut):'my%data = parse($ str);我的$ data_ref = \%data;' – memowe

+0

獲得對返回散列引用的替代方法可能是'my $ data_ref = {parse($ str)};' – memowe

回答

-1
sub returnThisHash { 
    return { status1 => "YES", value1 => 100, status2 => "NO", value2 => 200 }; 
} 
+0

這幾乎不能解決如何從字符串中提取這些信息。 – tripleee

+0

是的,因爲這是一個糟糕的問題。它提供了一個他希望額外提供散列的數據的例子,所以實際上它回答了他對該字符串的問題。 –

+0

這是一個邪惡的。 :D – memowe

1
#!/usr/bin/perl 
use warnings; 

$\="\n"; 

sub convStr { 
     my $str = $_[0]; 
     my %h1=(); 
     while ($str =~m/(\w+)\s+:\s+(\w+)/g) { 
       $h1{$1} =$2; 
     } 
     return \%h1; 
} 

my $str = "list 
    XYZ 

    status1 : YES 
    value1  : 100 
    status2  : NO 
    value2  : 200 
Thats all"; 

my $href=convStr($str); 

foreach (keys(%$href)) { 
     print $_ , "=>", $href->{$_}; 
} 

在運行,我得到:

status2=>NO 
value1=>100 
status1=>YES 
value2=>200 
0
my %hhash; 
    my @lines = split /\s+\n/, $str; 
      foreach (@lines) 
      { 
      $_=~s/^\s+//g; 
      if(/:/) 
      { 
      $key=(split(/:/))[0]; 
      $value=(split(/:/))[1]; 
      $hhash{$key}=$value; 
      } 
      } 
11

像往常一樣,有做不止一種方法。這裏來五點。

純正則表達式(YEAH!)

我認爲這是最酷的一個。正則表達式返回所有捕獲的列表,它正是我們要初始化與散列表:

my %regex = $str =~ /(\S+)\s*:\s*(\S+)/g; 

迭代

這是大多數程序員的最直接的方法,我想:

my @lines  = split /\R/ => $str; 
my %iterative =(); 
for (@lines) { 
    next unless /(\S+)\s*:\s*(\S+)/; 
    $iterative{$1} = $2; 
} 

這裏沒有解釋。我先將split中的字符串換行,然後遍歷它們,留下看起來不像foo : bar的行。完成。

列表處理

寫的一切作爲一個大名單的表達感覺有點hackish的,但也許這是有趣的,以瞭解更多的方式來表達的東西:

my %list = map  { /(\S+)\s*:\s*(\S+)/ and $1 => $2 } 
      grep { /:/ } 
      split /\R/ => $str; 

讀取,以左權:就像在上面的例子中,我們從分割字符串開始。 grep過濾:的行,並在最終映射中,使用一個鍵和一個值對長度爲二的列表中的匹配行字符串進行轉換。

名單減少List::Util

不平凡使用情況減少功能是非常罕見的。這裏有一個,基於從上面的列表方法,返回一個哈希參考

my $reduced = reduce { 
    $a = { $a =~ /(\S+)\s*:\s*(\S+)/ } unless ref $a; 
    $a->{$1} = $2 if $b =~ /(\S+)\s*:\s*(\S+)/; 
    return $a; 
} grep { /:/ } split /\R/ => $str; 

狀態機

這裏有一個有趣的一個正則表達式與使用僅空格分隔。它需要保持狀態的軌跡:

# preparations 
my $state = 'idle'; 
my $buffer = undef; 
my %state =(); 
my @words = split /\s+/ => $str; 

# loop over words 
for my $word (@words) { 

    # last word was a key 
    if ($state eq 'idle' and $word eq ':') { 
     $state = 'got_key'; 
    } 

    # this is a value for the key in buffer 
    elsif ($state eq 'got_key') { 
     $state{$buffer} = $word; 
     $state   = 'idle'; 
     $buffer   = undef; 
    } 

    # remember this word 
    else { 
     $buffer = $word; 
    } 
} 
+2

那個尷尬的時刻,當你意識到你不能一勞永逸。 –

+1

實際上想到了降低其他人來彌補它。 –

2

只是爲了好玩(請注意,我建議使用memowe的之一)這裏是一個(AB)使用YAML:

#!/usr/bin/env perl 

use strict; 
use warnings; 

use YAML; 

my $str = "list 
    XYZ 

    status1 : YES 
    value1  : 100 
    status2  : NO 
    value2  : 200 
Thats all"; 

$str = join "\n", grep { /:/ } split "\n", $str; 
my $hash = Load "$str\n"; 
+0

很酷,我喜歡它。 :) – memowe

相關問題