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

pretend %data contains something like 12::34::56::78::90::09

No matter how many things are in my hash, it only prints data for the last key. What am I doing wrong? (I'm trying to substitute for each and every key and have the results be dynamic per it's own data)

print <<"ALL"; <table width="470" border="0"> <form name="extract" method="post" action=""> <tr><td colspan="2"><textarea name="specifics" cols="40" rows="5" id=" +specifics">$specifics</textarea></td></tr> <tr><td><input type="submit" name="submit1" value="submit"></td></tr> </form> </table> ALL if (param('submit1')) { foreach (sort keys %data) { my ($a, $b, $c, $d, $e, $f) = split(/::/, $data{$_}); $specifics =~ s/\[a\]/a/g; $specifics =~ s/\[b\]/b/g; $specifics =~ s/\[$_\]/$data{$_}/g; $specifics =~ s/\[c\]/$c/g; $specifics =~ s/\[d\]/$d/g; $specifics =~ s/\[e\]/$e/g; $specifics =~ s/\[f\]/$f/g; print "$specifics<br>"; exit; } }

Replies are listed 'Best First'.
Re: Printing last element of hash (unintentionally)
by Joost (Canon) on Jan 03, 2004 at 21:06 UTC
    pretend %data contains something like 12::34::56::78::90::09

    I'm closing my eyes and pretening really hard..... No, doesn't work..... You seem to be misinformed about the structure of hashes in Perl. You cannot have a hash containing one element, a hash (in Perl) contains key/value pairs. Please show where you set the data in %data.

    Also, this code:

    $specifics =~ s/\[a\]/a/g; $specifics =~ s/\[b\]/b/g;
    Replaces all occurences of "[a]" and "[b]" with "a" and "b" respectively; don't you mean $specifics =~ s/\[a\]/$a/g; instead?

    Also also, $specifics is not being assigned any value in the piece of code you posted.

    I think your problem lies in one or more of the following points (I'm using Devel::PSI here, so I might be wrong):

    1. You assing something to %data that does not fit in a hash in one way or the other.
    2. Your use of split(/::/, $data{$_}); suggests you'd be better of using arrayrefs as values.
    3. You are trying to be really clever with user input that doesn't confirm to your expectations.
    Please explaing what you are trying to do, and then show how you are trying to accomplish it. Somebody might be able to help you more than I am at this point.

    Good luck,
    Joost.

      #!/usr/bin/perl my %data; my $data = "data.dbm"; my $lookup = url_param('lookup'); tie %data, 'SDBM_File', $data, O_CREAT | O_RDWR, 0644; if ( !tied %data ) { print "error $!.\n"; } print header(); print start_html(); print <<"ALL"; <table width="470" border="0"> <form name="extract" method="post" action="extract.pl"> <tr><td colspan="2"><textarea name="specifics" cols="40" rows="5" id=" +specifics">$specifics</textarea></td></tr> <tr><td><input type="submit" name="submit1" value="submit"></td></tr> </form> </table> ALL if (param('submit1')) { foreach (sort keys %data) { my ($a, $b, $c, $d, $e, $f) = split(/::/, $data{$_}); $specifics =~ s/\[a\]/$a/g; $specifics =~ s/\[b\]/$b/g; $specifics =~ s/\[more\]/$data{$_}/g; $specifics =~ s/\[c\]/$c/g; $specifics =~ s/\[d\]/$d/g; $specifics =~ s/\[e\]/$e/g; $specifics =~ s/\[f\]/$f/g; print "$specifics<br>"; } }
        $specifics =~ s/\[more\]/$data{$_}/g; Replaces all occurences of [more] with the current value of $data{$_}. You are using this code in a loop that iterates over the entries of the hash, but unless the values in %data acutally contain the literal string [more], only the first iteration will match.

        That is probably a problem. :-)

        I'm still not sure what you want to do, and if the hash actually contains what you think it does, though.

        Please also try running your code with:

        #!/usr/bin/perl -wT use strict;
        That will show some other problems in the code you posted above (you probably just posted a snipped of the code, but it suggests more things are going wrong than you are aware of)

        Joost.

Re: Printing last element of hash (unintentionally)
by revdiablo (Prior) on Jan 03, 2004 at 21:21 UTC

    The biggest thing that stands out at me about this code is your use of $a .. $f for variable names. These are undescriptive and silly. Perhaps you should just use an array, as in my @record = split /::/, $data{$_}; (it's up to you to come up with a better array name, of course). Not only are the variables unhelpful, but using $a and $b is probably a bad idea. These variables are "special" due to their use in sort, and should not be used except for that purpose. For details on this, check perlvar.

    As for the actual problem, I'm not sure why you're not getting all your data printed. Perhaps you're Suffering from Buffering.

    Update: now that I see you've posted more (all?) of your code, another thing stands out at me. Where does $specifics come from? I don't see it assigned anywhere. Perhaps you're thinking it will be set to whatever value was submitted in your textarea input, but that doesn't happen automatically, you'd have to assign it yourself.

Re: Printing last element of hash (unintentionally)
by chromatic (Archbishop) on Jan 03, 2004 at 20:56 UTC

    That exit could be the culprit, if you want the loop to execute more than once. :)

      That could have been a reason, but in my copy I commented it out and it still does the same thing. Only the last key gets printed.
Re: Printing last element of hash (unintentionally)
by TomDLux (Vicar) on Jan 04, 2004 at 01:10 UTC

    $specifics is never declared and never assigned a value. Therefore is it an empty string at the beginning of your program, and an empty string in the HTML, and an empty string at the final print.

    P.S. You loop over all the keys in %data, and exit the program after the first iteration of the loop.

    P.P.S. I suspect you intend the code to have a use CGI;

    --
    TTTATCGGTCGTTATATAGATGTTTGCA