在perl中将字符串解析为哈希结构

Dco*_*der 1 perl hash parsing

我有以下字符串:

$str = "list
    XYZ

    status1    : YES
    value1     : 100
    status2      : NO
    value2     : 200
Thats all";       
Run Code Online (Sandbox Code Playgroud)

我想用一个函数,它接受这个字符串作为输入,并返回一个散列把它转换成一个哈希status1作为密钥,并YES作为的例子.

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

mem*_*owe 13

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

纯正则表达式(YEAH!)

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

my %regex = $str =~ /(\S+)\s*:\s*(\S+)/g;
Run Code Online (Sandbox Code Playgroud)

迭代

对于大多数程序员来说,这是最简单的方法,我认为:

my @lines       = split /\R/ => $str;
my %iterative   = ();
for (@lines) {
    next unless /(\S+)\s*:\s*(\S+)/;
    $iterative{$1} = $2;
}
Run Code Online (Sandbox Code Playgroud)

这里没什么可解释的.我首先split是行中的字符串,然后迭代它们,留下看起来不像的行foo : bar.完成.

列表处理

把所有内容写成一个大表单表达感觉有点hackish,但也许有趣的是学习更多表达方式:

my %list =  map     { /(\S+)\s*:\s*(\S+)/ and $1 => $2 }
            grep    { /:/ }
            split   /\R/ => $str;
Run Code Online (Sandbox Code Playgroud)

从右到左阅读:与上面的例子一样,我们首先将字符串拆分为行.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;
Run Code Online (Sandbox Code Playgroud)

状态机

这是一个有趣的,仅用于白色空间分离的正则表达式.它需要跟踪状态:

# 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 那个尴尬的时刻,当你意识到你不能不止一次上升. (2认同)