我有以下字符串:解析字符串转换为哈希结构在Perl
$str = "list
XYZ
status1 : YES
value1 : 100
status2 : NO
value2 : 200
Thats all";
我想用一个函数,它接受这个字符串作为输入,并返回与status1
为哈希把它转换成一个散列例如,密钥和YES
作为值。
如何做?
以及如何引用返回的散列?
我有以下字符串:解析字符串转换为哈希结构在Perl
$str = "list
XYZ
status1 : YES
value1 : 100
status2 : NO
value2 : 200
Thats all";
我想用一个函数,它接受这个字符串作为输入,并返回与status1
为哈希把它转换成一个散列例如,密钥和YES
作为值。
如何做?
以及如何引用返回的散列?
#!/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;
}
}
像往常一样,有做不止一种方法。这里来五点。
我认为这是最酷的一个。正则表达式返回所有捕获的列表,它正是我们要初始化与散列表:
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
过滤:
的行,并在最终映射中,使用一个键和一个值对长度为二的列表中的匹配行字符串进行转换。
不平凡使用情况减少功能是非常罕见的。这里有一个,基于从上面的列表方法,返回一个哈希参考:
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";
很酷,我喜欢它。 :) – memowe
问题不明确界限是什么。我们应该假设冒号后面的第一个非空格标记是否为值,而不是包含由冒号分隔的两个标记的行上的东西应该被忽略? – tripleee
关于引用返回散列的最后一个问题与解析问题无关,[很平凡](http://p3rl.org/perlreftut):'my%data = parse($ str);我的$ data_ref = \%data;' – memowe
获得对返回散列引用的替代方法可能是'my $ data_ref = {parse($ str)};' – memowe