我有以下字符串:解析字符串轉換爲哈希結構在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