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

Greetings Brothers! Got a weird one for you.

I'm doing some testing, and basically I'm wanting to enter a hash at the command line, like this:

./test.pl r,2,g,2,w,1
And so I do this in my code:
#!/usr/bin/perl use Data::Dumper; my $arg = shift; my %actualhash = eval $arg; print Dumper \%actualhash;
And indeed, for the argument given above, it gives this result:
$VAR1 = { 'w' => 1, 'r' => 2, 'g' => 2 };
So everything is fine and dandy, right? However, I've discovered that if I try to use a 'q' as a hash key the program yields:
./test.pl r,2,g,2,w,1,q,1 $VAR1 = {};
So in short--what is up with that? Hepl!

Replies are listed 'Best First'.
Re: eval doesn't like the letter 'q'?
by davido (Cardinal) on Aug 06, 2011 at 17:09 UTC

    use strict; use warnings; use Data::Dumper; my %actualhash = split /,/, shift; print Dumper \%actualhash;

    eval takes whatever you hand to it and tries to compile it as code. So if you hand it print "Hello world.\n" it will print Hello World. Notice how we used quotes? So how about if we hand it say 'Hello world.';? We get the same output (if we use the say feature). And since q// is synonymous with single quotes, we can write that as, eval 'say q/Hello world./;'.

    But we also know that the q// operator allows you to use other delimiters, such as q{}, or even q,, (the latter is handy for obfu, and confusing for real world code). By now you should be seeing why putting q, in your input string that you eval may be a problem.

    This is an example of why everyone gets nervous and pops a blood pressure pill whenever they start talking about the string form of eval in the same conversation as 'raw user input'. Taint mode would make the very concept of evaling @ARGV args fatal.


    Dave

      ROFLMAO the delimiters, of course! I don't think I ever would have figured that out. And that neatly explains the error message, which I hadn't made sense of, yet.

      Thanks Dave!

      P.S. Don't worry I'm not mad enough to eval untrusted user input, even untainted quite frankly, as I don't think I'm smart enough to untaint perfectly. I'm just doing this for a little utility testing script, which, for the remainder of it's short life, will only be taking input from me personally :-)

Re: eval doesn't like the letter 'q'?
by Corion (Patriarch) on Aug 06, 2011 at 16:54 UTC

    When eval fails, I often find it enlightening to look at the code without the eval. I think Perl will tell you what it does not like about your code. Perl will also tell you about what it does not like when using eval in $@.

    In your case, look at perlop, especially the "Quotes and Quote-like operators". If you want something treated as a string for a hash, properly quote it instead of using barewords.

      Awesome Corion, great answer! And you've pinned the tail on the donkey--I was overconfident in my knowledge and thought I knew what I was doing when I didn't :-)

      However, now I'm wondering why it ever works at all! In my test I did this:

      #!/usr/bin/perl use Data::Dumper; my $arg = shift; my %actualhash = eval $arg; print Dumper \%actualhash; #old bad way my %badhash = ('r,2,g,2,w,1'); #if you don't think too hard, this look +s correct. print "\n%badhash:\n"; print Dumper \%badhash; print $@; my %hash = ('r',2,'g',2,'w',1); print "\n%hash:\n"; print Dumper \%hash; #print $@; unclutter output for posting to perlmonks--it just repeats +the first error, of course my @array = qw/r 2 g 2 w 1/; my %newhash = @array; print "\npassing through qw:\n"; print Dumper \%newhash; #print $@;
      Which yields:
      rasto@frodo:~/cheat$ ./test.pl 'r,2,g,2,w,1,q,1' $VAR1 = {}; %badhash: $VAR1 = { 'r,2,g,2,w,1' => undef }; Can't find string terminator "," anywhere before EOF at (eval 1) line +1. %hash: $VAR1 = { 'w' => 1, 'r' => 2, 'g' => 2 }; passing through qw: $VAR1 = { 'w' => '1', 'r' => '2', 'g' => '2' };
      So indeed, when I saw:
      $VAR1 = { 'r,2,g,2,w,1' => undef };
      It became obvious that I had a syntax error and I quickly saw the problem--fuzzy thinking on my part :-)

      But what's weird then is why it works at all, and why it stops working when adding a 'q'. I'm really quite curious now, although for my practical purposes it is only an intellectual excersize.

      I'm thinking for convenience I'll just pass it through 'qw' as I did in the test above, which will actually make it more convenient to type my arguments, lol! ;-)

      Thanks again for the excellent answer that taught me a problem solving skill, as opposed to simply answering :-D

        But what's weird then is why it works at all, and why it stops working when adding a 'q'

        Because you don't realise that q is an operator, and r, g and w aren't.