如何将字符串分解为哈希?

时间:2011-10-17 03:52:44

标签: string perl parameters explode

我有一个字符串

"myhashkey?key1=val1&key2=val2&key3=val3&key4=val4"

我想要爆炸

myhashkey => {
   key1 => val1,
   key2 => val2,
   key3 => val3
}

我也想把它折回到同一个字符串。

到目前为止,我提出的内容非常混乱,使用索引并尝试手动构建值

        $arg = $_[0];

#if arg has = it may be key=val string
        if(index($arg,'=') > -1 ){

#if arg has & character it might be key=val&key1=val

            if(index($arg,'&') > -1 ){

                #$arg =~ m/[=&\?]/
                @r = split(/[=&\?]/,$arg);
                my $hashkey = shift(@r)
                my %values = @r;
                return $class->$orig( key => $k, $value => \%values );
                ... 

            }else{
                @r = split('=',$arg);
                return ( key => $r[0], $value => $r[1] );
            }

        }

我不知道index(),split()和join()函数与其他实现此功能的方法相比有多昂贵。我想也许我可以使用map + grep,但我不确定如何为grep创建rergex。

我也不想重新发明轮子,所以希望有人能更好地了解如何做到这一点。

更新 BTW这发生在Moose BUILDARGS子系统中,所以我不想每次都使用类似URI的模块来解析字符串。

这就是我在BUILDARGS中使用该功能的方法

my $w = My::Param->new( 'hashkey?key1=val1&key2=val2&key3=val3');
my $x = My::Param->new( key => 'x', value => '7' );
my $y = My::Param->new( 'y=123' );

在打印翻转器(*)

上生成此项
{ 'key1' => 'val1', 'key2' => 'val2', 'key3' => 'val3' }
bless( { 'key' => 'hashkey', 'meta_info' => [ #0 'hashkey?key1=val1&key2=val2&key3=val3' ], 'value' => { 'key1' => 'val1', 'key2' => 'val2', 'key3' => 'val3' } }, 'My::Param' )
bless( { 'key' => 'x', 'meta_info' => [ #0 'key', #1 'x', #2 'value', #3 '7' ], 'value' => '7' }, 'My::Param' )
bless( { 'key' => 'y', 'meta_info' => [ #0 'y=123' ], 'value' => '123' }, 'My:Param' )

2 个答案:

答案 0 :(得分:10)

在这种情况下,已经发明的轮子名为URI

$ perl -MData::Dumper -MURI -e'
    $uri = URI->new("myhashkey?key1=val1&key2=val2&key3=val3&key4=val4");
    $h{ $uri->path } = { $uri->query_form };
    print Dumper(\%h);
'

答案 1 :(得分:3)

虽然这可行(1):

my $str = "myhashkey?key1=val1&key2=val2&key3=val3&key4=val4";

my ($path,$data) = split /\?/, $str, 2;
my %h = (
         $path => {
             map {
                 split /=/, $_, 2
             } split /\&/, $data
         }
        );

use Data::Dumper;
print Dumper \%h;

我认为你反对使用URI是一个过早优化的例子。除非你知道开销很大,否则不要冒汗。

(1) - 限制包括处理所需文本中的&'s等内容。在正常情况下,例如URI,这是使用%转义序列处理的。但是,我没有处理上述代码的代码。添加(其中的另一个地图)并不一定很困难,但是这可能很容易使编码维护比直接使用URI并且产生任何(可能是可忽略的)开销更加昂贵。