我有以下字符串:
$str = "list
XYZ
status1 : YES
value1 : 100
status2 : NO
value2 : 200
Thats all";
我想使用一个函数将其转换为哈希,该函数将此字符串作为输入并返回一个哈希,例如status1
作为键和YES
作为值。
怎么做?
以及如何引用返回的哈希?
像往常一样,有不止一种方法可以做到这一点。来了五个。
我认为这是最酷的一个。正则表达式返回所有捕获的列表,这正是我们想要初始化散列的列表:
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;
}
}
只是为了好玩(请注意,我建议使用 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";
#!/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
my %hhash;
my @lines = split /\s+\n/, $str;
foreach (@lines)
{
$_=~s/^\s+//g;
if(/:/)
{
$key=(split(/:/))[0];
$value=(split(/:/))[1];
$hhash{$key}=$value;
}
}