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

Fellow Monks,

I want to print the contants of each array in the data section, using $_ or @_ doesn't work, how can I do this?
while (<DATA>){ print $_; } __DATA__ @array1 @array2 @array3
Thanks in advance,
Jonathan

Replies are listed 'Best First'.
Re: printing a scalar as an array
by brian_d_foy (Abbot) on Feb 23, 2005 at 12:11 UTC

    There are a couple of ways to go from a variable name in a string to its value, and they are both pretty evil.

    You could try it with a soft reference, which is bad enough that it has its own little area in the strict module.

    #!/usr/bin/perl @array1 = qw( a b c ); @array2 = qw( x y z ); @array3 = qw( 3 9 6 ); while (<DATA>){ chomp; no strict refs; s/^@//; print "@{$_}\n"; }

    You could do it with the string form of eval(), but then you have to make sure you have something safe in the string you are about to eval. Someone could sneak something into the input and execute it as perl code (not good).

    #!/usr/bin/perl @array1 = qw( a b c ); @array2 = qw( x y z ); @array3 = qw( 3 9 6 ); while (<DATA>){ eval qq|print "$_"|; }

    You can also create a jump table so you can look up the value in a hash. You use the input string as the hash key. If the input value is not a key in the hash, nothing bad happens.

    #!/usr/bin/perl @array1 = qw( a b c ); @array2 = qw( x y z ); @array3 = qw( 3 9 6 ); my %hash = ( '@array1' => \@array1, '@array2' => \@array2, '@array3' => \@array3, ); while (<DATA>){ chomp; print "@{ $hash{$_} }\n"; } __DATA__ @array1 @array2 @array3
    --
    brian d foy <bdfoy@cpan.org>
      Shouldn't that be
      #!perl @array1 = qw( a b c ); @array2 = qw( x y z ); @array3 = qw( 3 9 6 ); while (<DATA>){ chomp; no strict refs; s/^@//; print "@{$_}\n"; } __DATA__ @array1 @array2 @array3
      UPDATE: All I had to do was put the arrays in the data section, never mind! (Originally I thought it was another problem.)
Re: printing a scalar as an array
by g0n (Priest) on Feb 23, 2005 at 12:09 UTC
    Jonathan,

    I'm not quite clear on what you want. If you have space separated data, you can use split as per sh1tn's post. On the other hand, if you want the array names in the __DATA__ block, you can do this:

    my @array1 = qw(1 2 3 4 5); my @array2 = qw(a b c d e); my @array3 = qw(6 7 8 9 0); my @array4 = qw(f g h i j); while (<DATA>) { foreach (eval($_)) { print "$_\n"; } print "\n"; } __DATA__ @array1; @array2; @array3; @array4;

    Update: Removed the quotes around $_ - quite right AM, my mistake. I tried various approaches to this problem, and the quotes were left over from a previous one.

    As to use strict, I always always always use strict. In future I'll leave it in when posting code snippets.

    VGhpcyBtZXNzYWdlIGludGVudGlvbmFsbHkgcG9pbnRsZXNz
      Very nice. Two things

      1) use the strictures

      2) if you use perl -l flag in the shebang you can avoid newlines at the end of your prints.

      #!perl -l use strict; use warnings; my @array1 = qw(1 2 3 4 5); my @array2 = qw(a b c d e); my @array3 = qw(6 7 8 9 0); my @array4 = qw(f g h i j); while (<DATA>) { foreach (eval("$_")) { print "$_"; } print ''; } __DATA__ @array1; @array2; @array3; @array4;

      UPDATE: I semi-agree with dragonchild. Personally, I just recently have been learning about the command line flags, and I have a lot of scripts where the "\n" everywhere does annoy me a bit, and I like not having to do it anymnore. But OTOH it is a bit obfu.

      UPDATE2: Dragonchild opined to me that "command line switches are for use in the command line" which on reflection seems reasonable enough. So if you agree with this point of view, delete the shebang line (#!) and just call the script using "perl -l". I think I may adopt this approach myself.

      Update3: (Red in the face) All right, all right! Save the -l for one-liners. Never mind.

        Somedays, I wish I could both ++ and -- a post. (Guess which one I ended up doing ...)

        Yes, use the strictures. But, don't use the commandline flags in a production script! Good Gods, man, are you trying to get the OP to write obfuscated code?!? Who looks at the shebang line? If I were to read that code, I would be going bonkers trying to figure out how the newline was getting in there, and I golf with -l on a regular basis. (He shoots a 14 handicap, in case you're wondering.)

        Being right, does not endow the right to be rude; politeness costs nothing.
        Being unknowing, is not the same as being stupid.
        Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
        Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

        Using the stricture adds, uhm, exactly nothing at all to the above program. It just increases the size of the program text. As for adding -l, I tend to only do that for only liners - with normal programs, you just want to use 'print' without newlines often enough to make it a nuisance (it's still possible by using printf though). I disagree with the remark in update2 though. "Just calling the script using 'perl -l'" is a major PITA. You want to call program by just typing their file names, having to remember which interpreter they need is hard - and it's even harder to remember which program needs which command line options! Not to mention that that will make debugging even harder than having -l mentioned in the she-bang line - that's easier to spot than the -l enforced on the program from the outside.

        However, I only write this node because of something else. What's with the quotes around $_ in the print statement? If you're going to nag about (pointless in this case) missing "use strict" statements, and whether or not to use -l vs. a newline, you should at least get rid of the not needed quotes around the variable.

Re: printing a scalar as an array
by sh1tn (Priest) on Feb 23, 2005 at 12:06 UTC
    while(<DATA>){ push @all, [ split '\s+', $_ ] } print "@$_\n" for @all __DATA__ 11 21 31 12 22 32 13 23 33
    Update Please, take a look at perldoc perldata.


      I should've been more descriptive... @array1, @array2 & @array3 are actual array names, these are arrays set up in different parts of the script, for example:
      @array1=qw(aa bb cc dd);
      etc.
      Jonathan