http://www.perlmonks.org?node_id=1016668

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

Dear All, I have did the pattern matching for agent_id field value in one log file. After that I have stored that values from $1 to another variable called $agent_id. For some values it contains the " ( double quotes ). Then I have substituted that double quotes. After that I have tried to store the correct values into array. But in array it is storing all the values into first index itself. But I want to store each value in different index.

Sample code:

if($line =~ /^.*:agent_id=>(.+?),/){ my $agent_id=$1; my $agent_id =~ s/\"//g; my @array=$agent_id; print $array[0]; }

I want to know how to store the values in array properly like each matched string in different index. Kindly provide me the solution for this issue.

Replies are listed 'Best First'.
Re: How to store matched $1 values one by one to array?
by kcott (Archbishop) on Feb 02, 2013 at 07:52 UTC

    G'day rekhasri,

    Welcome to the monastery.

    Take a look at the push function.

    I can't see anywhere in your code where you're adding anything to an array. However, what you've written is rather difficult to read: take a look at Markup in the Monastery.

    You probably want something like:

    my @agent_ids; # outside logfile reading loop ... if (...) { ... push @agent_ids, $agent_id; }

    -- Ken

      I forgot to add that array line in my code. Now I have added that line in my first question. Sorry for the inconvenience.

        Well, it's not an inconvenience, but that does now highlight where you're going wrong.

        Declare your array outside of whatever loop iterates over your logfile and replace my @array=$agent_id; with a push statement, as I indicated.

        -- Ken

Re: How to store matched $1 values one by one to array?
by parv (Parson) on Feb 02, 2013 at 07:47 UTC

    Please make the code portion readable, a hint about which was provided just above the entry box ...

    Use: <p> text here (a paragraph) </p> and: <code> code here </code> to format your post; it's "PerlMonks-approved HTML":
    ... when you made your post.
      I have changed my question format as per your suggestion. Thanks..
Re: How to store matched $1 values one by one to array?
by AnomalousMonk (Archbishop) on Feb 02, 2013 at 12:14 UTC

    Here's something that may be close to what you're seeking:

    >perl -wMstrict -le "my $line = 'xxx:agent_id=>foo,yyy:agent_id=>b\"a\"r,zzz:agent_id=>\"baz\",qqq' +; print qq{'$line'}; ;; my @agents; while ($line =~ m{ :agent_id=> (.+?) , }xmsg) { my $agent_id = $1; printf qq{extracted agent id: '$agent_id' }; $agent_id =~ s/\"//g; print qq{fixed agent id: '$agent_id'}; push @agents, $agent_id; } printf qq{'$_' } for @agents; " 'xxx:agent_id=>foo,yyy:agent_id=>b"a"r,zzz:agent_id=>"baz",qqq' extracted agent id: 'foo' fixed agent id: 'foo' extracted agent id: 'b"a"r' fixed agent id: 'bar' extracted agent id: '"baz"' fixed agent id: 'baz' 'foo' 'bar' 'baz'

    In addition to perlrequick, see also perlre (the guts and the glory) and perlretut (a good tutorial, highly recommended).

Re: How to store matched $1 values one by one to array? (perlrequick)
by Anonymous Monk on Feb 02, 2013 at 07:56 UTC
Re: How to store matched $1 values one by one to array?
by johngg (Canon) on Feb 02, 2013 at 13:40 UTC

    Note that another, perhaps safer, way of capturing everything after "agent_id=>" up to but not including a comma is to use use a negated character class ([^,]+) meaning one or more of anything that isn't a comma rather than a non-greedy match of anything (.+?). You can also populate your array, let's call it @agents, in one fell swoop by using a global match (g flag) and a map within which we substitute away the double-quotes.

    $ perl -Mstrict -Mwarnings -MData::Dumper -e ' > my $line = > q{xxx:agent_id=>foo,yyy:agent_id=>b"a"r,zzz:agent_id=>"baz",qqq}; > > my @agents = > map { s{"}{}g; $_ } > $line =~ m{ :agent_id=> ( [^,]+ ) }xg; > > print Data::Dumper->Dumpxs( [ \ @agents ], [ qw{ *agents } ] );' @agents = ( 'foo', 'bar', 'baz' ); $

    I hope this is helpful.

    Cheers,

    JohnGG

      A minor variation using the  \K (5.10+) and  s///r (5.14+) regex operators, and no capture groups. (Note: I use  \x22 instead of  " (double-quote) in the  s///r substitution because the Windoze CLI gets a little freaky over unpaired double-quotes.)

      >perl -wMstrict -MData::Dump -le "my $line = q{xxx:agent_id=>foo,yyy:agent_id=>b\"a\"r,zzz:agent_id=>\"baz\",qqq +}; ;; my @agents = map s{\x22}{}xmsgr, $line =~ m{ :agent_id=> \K [^,]+ }xmsg; ;; dd \@agents; " ["foo", "bar", "baz"]