2012-10-22 148 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

相关问题