Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

problem with array

by texuser74 (Monk)
on Aug 20, 2008 at 03:52 UTC ( [id://705389]=perlquestion: print w/replies, xml ) Need Help??

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

Dear Monks,
I have an input file like this:
<ref id="ref1"> <ref id="ref2"> <ref id="ref3"> </end> <ref id="ref4"> <ref id="ref5"> </end> <ref id="ref6"> <ref id="ref7"> <ref id="ref8"> </end>
I need an output like:
New Group: ref1 ref2 ref3 New Group: ref4 ref5 New Group: ref6 ref7 ref8
i.e. i need to store the values in an array and print until i encounter </end>.

but my current code produces wrong output, pls review and advice.

open(IN, '<', "test.in") || die "\nCan't open test.in\n $!\n"; while(<IN>) { if(<end/>){my @avalues; if(/<ref id="(.*?)">/){ @avalues = (@avalues,$1); }print "\nNew Group: @avalues" } } close(IN);
Thanks in advance

Replies are listed 'Best First'.
Re: problem with array
by GrandFather (Saint) on Aug 20, 2008 at 04:25 UTC

    There are a stack of things that look odd in your code with the top of the list being if(<end/>){. However, the following solution to your problem as expressed may help:

    use strict; use warnings; my $str = <<DATA; <ref id="ref1"> <ref id="ref2"> <ref id="ref3"> </end> <ref id="ref4"> <ref id="ref5"> </end> <ref id="ref6"> <ref id="ref7"> <ref id="ref8"> </end> DATA open IN, '<', \$str || die "\nCan't open test.in\n $!\n"; local $/ = '</end>'; while (<IN>) { my @avalues = /="([^"]+)"/g; next unless @avalues; print "New Group: @avalues\n"; } close (IN);

    Prints:

    New Group: ref1 ref2 ref3 New Group: ref4 ref5 New Group: ref6 ref7 ref8

    Note the \$str trick is just to avoid requiring a file external to the sample code.


    Perl reduces RSI - it saves typing
      Note the \$str trick is just to avoid requiring a file external to the sample code.

      I tend to open the filehandle directly on a reference to the heredoc to avoid using a variable. You may consider that is going too far :-)

      open my $inFH, q{<}, \ << 'EOD' or die qq{open: << heredoc: $!\n}; .... .... EOD

      If the filehandle was to be opened in some inner scope I would use a variable as you have done to avoid the heredoc messing up indentation.

      Cheers,

      JohnGG

      Hi, Thanks for your answers. now its working fine.
Re: problem with array
by NetWallah (Canon) on Aug 20, 2008 at 04:37 UTC
    Others have given more advanced solutions to your issue.

    The main issues with your code were:

    • The expression <end/> is a FILE GLOB. Please look that up since this was obviously unintentional
    • The expression was incorrect in another sense: the data has "/end" with the slash before "end"
    • The logic to collect information was incorrect, and
    • @values was wrongly scoped
    With these corrected, the following modification to your code provides the expected answer:
    use strict; #open(IN, '<', "test.in") || die "\nCan't open test.in\n $!\n"; my @values; while(<DATA>) { if(/<ref id="(.*?)">/){ push @values ,$1; next; } if(m|</end>|){ print "New Group: @values \n"; @values=(); # Empty it } } #close(IN); __DATA__ <ref id="ref1"> <ref id="ref2"> <ref id="ref3"> </end> <ref id="ref4"> <ref id="ref5"> </end> <ref id="ref6"> <ref id="ref7"> <ref id="ref8"> </end>

         Have you been high today? I see the nuns are gay! My brother yelled to me...I love you inside Ed - Benny Lava, by Buffalax

Re: problem with array
by jwkrahn (Abbot) on Aug 20, 2008 at 04:19 UTC
    $ echo '<ref id="ref1"> <ref id="ref2"> <ref id="ref3"> </end> <ref id="ref4"> <ref id="ref5"> </end> <ref id="ref6"> <ref id="ref7"> <ref id="ref8"> </end>' | perl -lne' if ( /<ref\s+id="([^"]+)">/ ) { push @x, $1 } elsif ( /<\/end>/ ) { print "New Group:", map " $_", splice @x } ' New Group: ref1 ref2 ref3 New Group: ref4 ref5 New Group: ref6 ref7 ref8
Re: problem with array
by ChOas (Curate) on Aug 20, 2008 at 06:29 UTC
    Personally I'm pretty fond of modifying the input record seperator:
    local $/="</end>\n"; my @group = map {[/<ref id="([^"]+)">/g]} <DATA>; print "New Group: @$_\n" for @group; __END__ <ref id="ref1"> <ref id="ref2"> <ref id="ref3"> </end> <ref id="ref4"> <ref id="ref5"> </end> <ref id="ref6"> <ref id="ref7"> <ref id="ref8"> </end>

    Outputs:
    New Group: ref1 ref2 ref3
    New Group: ref4 ref5
    New Group: ref6 ref7 ref8

    (edit: Ah, so is GrandFather, read right past his response, 'ooops')

    GreetZ!,
      ChOas

    print "profeth still\n" if /bird|devil/;
Re: problem with array
by repellent (Priest) on Aug 20, 2008 at 04:54 UTC
    Do you only care about the printed output?

    my $acc = "New Group:"; while (<IN>) { chomp(); $acc .= " $1" if m|<ref\s+id="([^"]+)">|; print "$acc\n" and $acc = "New Group:" if m|</end>|; }

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (4)
As of 2024-04-25 23:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found