Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

regex question

by morgon (Priest)
on Apr 01, 2020 at 17:10 UTC ( #11114912=perlquestion: print w/replies, xml ) Need Help??

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

Hi,

I would like to turn a multiline string that looks like

1 A 2 B
into a hash that looks like
{ 1 => "A", 2 => "B", }
And I tought this was easy enough, however to my surprise this does not work:
use strict; use Data::Dumper; my $s = "1 A\n2 B\n"; my %h =map { $1 => $2 } $s =~ /(\d+)\s+(\S+)/mg; print Dumper(\%h);
It produces
$VAR1 = { '2' => 'B' };
Could someone please explain to me what is going on here?

Many thanks!

Replies are listed 'Best First'.
Re: regex question
by Corion (Pope) on Apr 01, 2020 at 17:16 UTC

    The match runs to completion before the map even starts.

    At the time your map runs, $1 and $2 are what they are at the end of the global match.

    Most likely you want pairs from List::Util:

    foreach my $pair ( pairs /(\d+)\s+(\S+)/mg ) { my ( $key, $value ) = @$pair; ... }

    ... or a while loop:

    $h{ $1 } = $2 while /(\d+)\s+(\S+)/mg;
Re: regex question
by AnomalousMonk (Bishop) on Apr 01, 2020 at 17:51 UTC

    Or even more simply:

    c:\@Work\Perl\monks>perl -wMstrict -le "use Data::Dumper; ;; my $s = qq{1 A\n2 B\n}; ;; my %h = $s =~ /(\d+)\s+(\S+)/g; print Dumper(\%h); " $VAR1 = { '1' => 'A', '2' => 'B' };


    Give a man a fish:  <%-{-{-{-<

Re: regex question
by AnomalousMonk (Bishop) on Apr 02, 2020 at 01:45 UTC

    morgon:   Further to Corion's post:

    [Corion]: The match runs to completion before the map even starts.

    At the time your map runs, $1 and $2 are what they are at the end of the global match.
    Here's an instrumented version of the OPed code to better (I hope) show what's happening:
    c:\@Work\Perl\monks>perl -wMstrict -le "use Data::Dumper; ;; my $s = \"1 A\n2 B\n33 foo\n\"; ;; my %h = map { print qq{in map: \$_ '$_' \$1 '$1' \$2 '$2'}; $1 => $2; } $s =~ /(\d+)\s+(\S+)/mg ; print Dumper(\%h); " in map: $_ '1' $1 '33' $2 'foo' in map: $_ 'A' $1 '33' $2 'foo' in map: $_ '2' $1 '33' $2 'foo' in map: $_ 'B' $1 '33' $2 'foo' in map: $_ '33' $1 '33' $2 'foo' in map: $_ 'foo' $1 '33' $2 'foo' $VAR1 = { '33' => 'foo' };
    (Note that this example doesn't take into account the revised data format specification suggested here. :)


    Give a man a fish:  <%-{-{-{-<

Re: regex question
by hippo (Chancellor) on Apr 01, 2020 at 17:53 UTC

    As Corion has answered your question, here's just a simpler (IMHO) approach to the task:

    #!/usr/bin/env perl use strict; use warnings; use Data::Dumper; my $s = "1 A\n2 B\n"; my %h = split /\s/, $s; print Dumper(\%h);
      Very imaginative, but in reality my lines look not like "1 A" but rather like "1 string1 string2 string3" and so your approach would not work anymore.

      But your idea is cool.

        Clear questions elicit clear and helpful answers. What should the content of your hash look like given the new data format? Do any of the other solutions given so far produce that structure | hash content?


        Give a man a fish:  <%-{-{-{-<

        If you want to match "1 string1" from "...\n1 string1 string2 string3\n...", use anchor '^', otherwise modifier 'm' is redundant. Did it help?
Re: regex question
by tybalt89 (Prior) on Apr 01, 2020 at 17:51 UTC
    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11114912 use warnings; my $s = "1 A\n2 B\n"; my %h = split ' ', $s; use Data::Dump 'dd'; dd \%h;

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (9)
As of 2021-01-27 17:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?