1

我有以下字符串:

$str = "list
    XYZ

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

我想使用一个函数将其转换为哈希,该函数将此字符串作为输入并返回一个哈希,例如status1作为YES作为

怎么做?
以及如何引用返回的哈希?

4

4 回答 4

14

像往常一样,有不止一种方法可以做到这一点。来了五个。

纯正则表达式(是的!)

我认为这是最酷的一个。正则表达式返回所有捕获的列表,这正是我们想要初始化散列的列表:

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过滤最终映射的行,:并在最终映射中转换匹配的行字符串在长度为 2 的列表中,带有一个键和一个值。

清单减少

List::Utilreduce函数的重要用例非常罕见。这是一个,基于上面的列表方法,返回一个哈希引用

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;
    }
}
于 2012-10-22T10:11:04.217 回答
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";
于 2012-10-22T18:29:01.313 回答
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
于 2012-10-22T09:04:44.340 回答
0
  my %hhash;
  my @lines = split /\s+\n/, $str;
          foreach (@lines)
          {
            $_=~s/^\s+//g;
            if(/:/)
            {
            $key=(split(/:/))[0];
            $value=(split(/:/))[1];
            $hhash{$key}=$value;
            }
          }
于 2012-10-22T09:27:00.027 回答