2011-10-17 3 views
0

나는 내가 같은 문자열이 다시 축소 할문자열을 해시로 분해하려면 어떻게해야합니까?

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

로 폭발 할 문자열

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

에게 있습니다.

지금까지 인덱스를 사용) (내가 얼마나 비싼 인덱스(), 분할을 모르는 손

 $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]); 
      } 

     } 

하여 값을 만들려고 꽤 지저분 마련했는지, join() 함수는 이것을 수행하는 다른 방법과 비교됩니다. 아마도 map + grep을 사용할 수 있다고 생각했지만 grep 용 regex를 만드는 방법을 알지 못했습니다.

나는 또한 바퀴를 재발 명하고 싶지 않으므로 누군가가 이것을 어떻게하는지 더 잘 알 수 있습니다.

은 BTW이 무스 BUILDARGS 하위에서 어떤 일이 일어나고 업데이트, 그래서 매번 문자열을 구문 분석 할 URI와 같은 모듈을 사용하지 않습니다.

이 내가

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'); 

BUILDARGS

에서 함수를 사용하여 인쇄 덤퍼 (*), 이미 발명 휠의 이름은이 경우

{ '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') 

답변

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); 
' 
+0

아를 URI를 사용합니다. 그거야. 하지만 하위가이 해시를 생성 할 때마다 URI 객체를 만들어야한다는 뜻입니까? BUILDARGS {} 하위에서이 일이 더 분명 해졌음을 알았습니다. 다른 방법이 있습니까? – qodeninja

+3

@nodebunny, 나는 당신의 요점을 보지 못했습니다. 그런데 URI 객체를 객체에 저장할 것을 고려 했습니까? "백만"유용한 방법에 즉시 액세스 할 수 있습니다. – ikegami

+0

예, 방금 시도했지만 작동합니다.], 나는 전체 URI 모듈을 필요로하지 않고 단지 param 구문 분석 만합니다. query_form 함수를 내보낼 수 있습니까? – qodeninja

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) - 제한 사항은 원하는 텍스트 안에 & 같은 것을 다루는 것을 포함합니다. URI와 같은 정상적인 상황에서는 % escape sequences로 처리됩니다. 그러나 위의 코드를 처리 할 코드가 없습니다. (다른 맵을 거기에 추가하는 것은 반드시 어렵지는 않겠지 만) URI를 직접 사용하고 포함 할 수있는 (무시할 수있는) 오버 헤드를 발생시키는 것보다 코딩 유지 보수가 훨씬 더 비쌉니다.

+0

+1을 가져 주셔서 감사합니다. 구분자가 URL-param-style은 아닐 수 있다는 점을 제외하고는 URI를 사용하는 것에 대해 이의를 제기 할 수는 없지만 여기서는 예제로 사용했습니다. 그것은 정말로 내가 폭발하려고하는 인코딩 된 문자열입니다.나는 당신이지도에서 그랬던 것을 좋아합니다.^_^ – qodeninja

+0

my ($ path, $ data) = m /([^?]+)\,(.*)/; my % h = map {split '='} split ('&', $ data); << - 나는 정규 표현식을 선호하므로 물음표가 데이터 부분에있을 수있다. –

관련 문제