Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

extracting the key value pairs from a string

by mnranjeeth (Novice)
on Jun 27, 2008 at 06:52 UTC ( [id://694325]=perlquestion: print w/replies, xml ) Need Help??

mnranjeeth has asked for the wisdom of the Perl Monks concerning the following question:

A string of the following format has to be parsed into a list of key-value pairs.
Example String: "     Key1: Value1    Key2: Value2 Key3:Value3"
The number of key-value pairs and the number of spaces between them is not fixed.

I need to extract each of the key value pairs in the string into a hash.
I tried forming a regex using the number of ":"'s that occur in the string as below:
my $s = ' ABC: 123 xyz: 100 def: YYY aaa: ZZZ'; my $count = my @order = $s =~ /:/sg; $regex = '(\w+:\s\w+)'.('\s+(\1)' x --$count); print $regex; if ($s =~ /$regex/){ print "regex works"; }
But the above code doesn't work .
Is there any other way of doing this?

Replies are listed 'Best First'.
Re: extracting the key value pairs from a string
by BrowserUk (Patriarch) on Jun 27, 2008 at 07:03 UTC
Re: extracting the key value pairs from a string
by waldner (Beadle) on Jun 27, 2008 at 09:17 UTC
    That looks way too complicated. Try this:
    my $s = ' ABC: 123 xyz: 100 def: YYY aaa: ZZZ'; my %hash= ($s=~/([^ :]+)/g);
      This is brilliant.... but what exactly is going on here?

        Hello alphacoorg, and welcome to the Monastery!

        $s=~/([^ :]+)/g

        The square brackets create a bracketed character class and the initial ^ (caret) negates what follows, so this character class matches any character other than a space or a colon. The + quantifier means one or more, and the surrounding parentheses create a capture group. Finally, the /g modifier creates a global match, and since the expression is evaluated in list context, the global match returns a list of matches.

        That is, the regular expression returns a list of the substrings in '   ABC: 123 xyz: 100    def: YYY    aaa: ZZZ' that do not contain space or colon characters:

        ("ABC", 123, "xyz", 100, "def", "YYY", "aaa", "ZZZ")

        (You can verify this yourself by assigning the output of the regular expression to an array instead of a hash, and then printing out the array.)

        In Perl, assigning a list to a hash populates the hash with key/value pairs taken in sequence from the list. So in this case, the hash is created with entries:

        "ABC" => 123, "xyz" => 100, etc.

        (Note that Perl’s “fat comma” =>, which is what you normally use when assigning key/value pairs to a hash, is really just an ordinary comma, functioning as a list separator, with the additional property that the expression on its left-hand side is turned into a string.)

        Hope that helps,

        Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: extracting the key value pairs from a string
by andreas1234567 (Vicar) on Jun 27, 2008 at 07:30 UTC
    Perhaps you will find String::Escape useful:
    $ perl -wl use String::Escape qw( string2hash hash2string ); use Data::Dumper; my $string = hash2string( ( foo => 1, bar => 2, tze => 3 ) ); print $string; my %hash = string2hash( $string ); print Dumper \%hash; __END__ foo=1 bar=2 tze=3 $VAR1 = { 'bar' => '2', 'foo' => '1', 'tze' => '3' };
    --
    No matter how great and destructive your problems may seem now, remember, you've probably only seen the tip of them. [1]
Re: extracting the key value pairs from a string
by oko1 (Deacon) on Jun 27, 2008 at 14:24 UTC

    As is often the case with Perl, you can cheat. :)

    #!/usr/bin/perl -w use strict; my $a = " a: b c: d e: f "; $a =~ y/://d; my %h = eval "qw/$a/"; # The Evil String Eval print "Key [$_] | Value [$h{$_}]\n" for keys %h;
    
    -- 
    Human history becomes more and more a race between education and catastrophe. -- HG Wells
    
Re: extracting the key value pairs from a string
by philipbailey (Curate) on Jun 27, 2008 at 08:31 UTC
    Or this?
    my $s = ' ABC: 123 xyz: 100 def: YYY aaa: ZZZ'; my %hash; for (split /[^:]\s+/, $s) { my ($key, $val) = split /:\s*/; next unless $key; $hash{$key} = $val; }
      split /[^:]\s+/, $s

      That's not going to do what you hoped as it will consume the last character of each value except the one at the end of the string. You can get around that by using a negative look-behind. I also use map to avoid the for loop and temporary variables.

      use strict; use warnings; use Data::Dumper; my $s = q{ ABC: 123 xyz: 100 def: YYY aaa: ZZZ}; my %extract = map { split m{\s*:\s*} } split m{(?<!:)\s+}, $s; print Data::Dumper->Dumpxs( [ \ %extract ], [ q{*extract} ] );

      This produces

      %extract = ( 'ABC' => '123', 'def' => 'YYY', 'aaa' => 'ZZZ', 'xyz' => '100' );

      I hope this is of interest.

      Cheers,

      JohnGG

Re: extracting the key value pairs from a string
by Zen (Deacon) on Jun 27, 2008 at 14:29 UTC
    Aside from the solution...the main problem here is you're trying to cram so much into single lines that you don't know what's going on. Slow down a little, especially when things aren't working.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://694325]
Approved by polettix
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (6)
As of 2024-04-23 11:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found