我有以下字符串:
$str = "list
XYZ
status1 : YES
value1 : 100
status2 : NO
value2 : 200
Thats all";
我想使用一个函数将其转换为哈希值,该函数将此字符串作为输入并返回一个哈希,status1
为 key ,YES
为值例如。
怎么做?
以及如何引用返回的哈希?
答案 0 :(得分:12)
与往常一样,有多种方法可以做到这一点。这里有五个。
我认为这是最酷的一个。正则表达式返回所有捕获的列表,这正是我们想要用以下内容初始化哈希的列表:
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::Util reduce 函数的非平凡用例非常罕见。这是一个,基于上面的列表方法,返回哈希引用:
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;
}
}
答案 1 :(得分:2)
只是为了好玩(请注意,我建议使用memowe' s)这里是(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";
答案 2 :(得分: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
答案 3 :(得分:0)
my %hhash;
my @lines = split /\s+\n/, $str;
foreach (@lines)
{
$_=~s/^\s+//g;
if(/:/)
{
$key=(split(/:/))[0];
$value=(split(/:/))[1];
$hhash{$key}=$value;
}
}