Problem with indirect variables

M

Marshall Dudley

Why can I not get the second variable to print it's value in the
following code?

$test = "Test String";
$form_data{'test'} = "form data variable";
foreach $string (test,"form_data{'test'}") {
print "$string = $$string\n";
}

perl test.pl
test = Test String
form_data{'test'} =

Thanks,

Marshall
 
B

Brian McCauley

Why can I not get the second variable to print it's value in the
following code?

Because expanding a symbolic reference just does a single look up in
the package symbol table. It does not evaluate an arbitrary string as
Perl code.
$test = "Test String";
$form_data{'test'} = "form data variable";
foreach $string (test,"form_data{'test'}") {
print "$string = $$string\n";

You are telling perl to look for single scalar package variable the
name of which is literally the string "form_data{'test'}". That is to
say there literally are braces and quote characters in the _name_ of
the scalar variable. I suspect you wanted to get at the value in the
hash %form_data associated with the key 'test'.

I'm now going to show you how you'd make Perl do what you thought
would happen

Do not actually do it.

To do so would be stupid**100.

Let me say that again, to actually do this would be stupid**100.

Is that clear?

OK here goes.

print "$string = ",eval( '$' . $string), "\n"; # Don't actually
do this!

Now, what was it you really wanted to do?
 
J

Jürgen Exner

Marshall said:
Why can I not get the second variable to print it's value in the
following code?

$test = "Test String";
$form_data{'test'} = "form data variable";
foreach $string (test,"form_data{'test'}") {
print "$string = $$string\n";


Had you enabled warnings then perl would have told you:
Use of uninitialized value in concatenation (.) or string at ....

In short: You do not have a variable that is named
form_data{'test'}

Besides that what you are trying to do is known as symbolic references and
it is A BAD IDEA!
See the FAQ "How can I use a variable as a variable name?" for details about
why and what to use instead.

jue
 
M

Marshall Dudley

Jürgen Exner said:
Had you enabled warnings then perl would have told you:
Use of uninitialized value in concatenation (.) or string at ....

In short: You do not have a variable that is named
form_data{'test'}

Besides that what you are trying to do is known as symbolic references and
it is A BAD IDEA!
See the FAQ "How can I use a variable as a variable name?" for details about
why and what to use instead.

jue
I looked at the faq, but did not really see anything applicable. Here
is the deal. I have been notified that I have clean up all my variables
that print to not allow any <, >, ', &, ( or ) in them to prevent cross
platform scripting hacking. So I have a confirmation page that prints
dozens of variables that are global variables, most of which are form
variables from the form input. So I wanted to have a list of the
variable names, and use one small section of code to do the
substitutions, like this:

foreach my $variable
(customer_number,"form_data{'Ecom_BillTo_Postal_Name_First'}","form_data{'Ecom_BillTo_Postal_Name_Last'}",
"form_data{'Ecom_BillTo_Company'}","form_data{'Ecom_BillTo_Postal_Street_Line1'}","form_data{'Ecom_BillTo_Postal_City'}",
"form_data{'Ecom_BillTo_Postal_StateProv'}","form_data{'Ecom_BillTo_PostalCode'}","bill_country,form_data{'Ecom_BillTo_Telecom_Phon
"form_data{'Ecom_BillTo_Online_Email'}","form_data{'Ecom_ShipTo_Postal_Name_First'}","form_data{'Ecom_ShipTo_Postal_Name_Last'}",
"form_data{'Ecom_ShipTo_Postal_Street_Line1'}","form_data{'Ecom_ShipTo_Postal_City'}","ship_country","form_data{'PO'}",
"$form_data{'Comments'}") {
$$variable =~ s/\</\&lt;/g;
$$variable =~ s/\>/\&gt;/g;
$$variable =~ s/\(/\(/g;
$$variable =~ s/\)/\)/g;
$$variable =~ s/\'/\'/g;
}

If I inline it, I end up with 5*18 or 90 lines of code in what should be
able to be done in 6 or 7.

Thanks,

Marshall
 
U

Uri Guttman

MD> I looked at the faq, but did not really see anything applicable. Here
MD> is the deal. I have been notified that I have clean up all my
MD> variables that print to not allow any <, >, ', &, ( or ) in them to
MD> prevent cross platform scripting hacking. So I have a confirmation
MD> page that prints dozens of variables that are global variables, most
MD> of which are form variables from the form input. So I wanted to have
MD> a list of the variable names, and use one small section of code to do
MD> the substitutions, like this:

you are thinking about this in a totally backwards way on several levels.

MD> foreach my $variable
MD> (customer_number,"form_data{'Ecom_BillTo_Postal_Name_First'}","form_data{'Ecom_BillTo_Postal_Name_Last'}",
MD> "form_data{'Ecom_BillTo_Company'}","form_data{'Ecom_BillTo_Postal_S

where did those 'variables' come from? show that code too. and as
several people have said, "form_data{'Ecom_BillTo_Postal_Name_First'}"
IS NOT A VARIABLE. it is not even a hash value as it has no normal perl
$hash{key} syntax (it is missing the leading $). i don't know what you
think it is nor where you learned it but it makes no sense in how you
describe it. it is a simple string expression. so it can't ever refer to
anything else in perl especially other 'variables' as it is not even a
proper variable name.

now you actually seem to have the values in a hash. i will assume that
the hash is named %form_data since it is perl. maybe it comes from some
bastard cgi parser (my main guess). so the first thing you need to do is
use a proper module CGI.pm to get your form params. but let's stick with
the hash for now and this is easily changed to use CGI.pm.


MD> $$variable =~ s/\</\&lt;/g;
MD> $$variable =~ s/\>/\&gt;/g;
MD> $$variable =~ s/\(/\(/g;
MD> $$variable =~ s/\)/\)/g;
MD> $$variable =~ s/\'/\'/g;

again, perl has modules for that. why are you reinventing wheels?


MD> If I inline it, I end up with 5*18 or 90 lines of code in what should
MD> be able to be done in 6 or 7.

if you used a module it would be 1 line.

use HTML::Entities

encode_entities $_ for values %form_data ;

now isn't that a bit easier to understand? and it works too!

so please learn more perl and stop beating your head against the
wall. your loop code above had NO VARIABLES so don't use that term and
then expect us to understand you.

uri
 
J

Jürgen Exner

Marshall said:
I looked at the faq, but did not really see anything applicable.

You were trying to do "$$string". This is dereferencing a symbolic
reference. Therefore the FAQ is very applicable.
Here
is the deal. I have been notified that I have clean up all my
variables that print to not allow any <, >, ', &, ( or ) in them to
prevent cross platform scripting hacking.

This seems like such a frequent task. I never use Perl for web site
development, but maybe it would be worthwhile to check CPAN if there isn't a
module that does this kink of cleanup already.
So I have a confirmation
page that prints dozens of variables that are global variables, most
of which are form variables from the form input. So I wanted to have
a list of the variable names, and use one small section of code to do
the substitutions, like this:

foreach my $variable
(customer_number,"form_data{'Ecom_BillTo_Postal_Name_First'}","form_data{'Ecom_BillTo_Postal_Name_Last'}",
"form_data{'Ecom_BillTo_Company'}","form_data{'Ecom_BillTo_Postal_Street_Line1'}","form_data{'Ecom_BillTo_Postal_City'}",

What is this "form_data{'xxxx'}"? Do you mean "$form_data{'xxxx'}"?
If yes, then you already got the hash that is suggested in the FAQ.

for my $variable(keys(%form_data)) {
"form_data{'Ecom_BillTo_Postal_StateProv'}","form_data{'Ecom_BillTo_PostalCode'}","bill_country,form_data{'Ecom_BillTo_Telecom_Phon
"form_data{'Ecom_BillTo_Online_Email'}","form_data{'Ecom_ShipTo_Postal_Name_First'}","form_data{'Ecom_ShipTo_Postal_Name_Last'}",
"form_data{'Ecom_ShipTo_Postal_Street_Line1'}","form_data{'Ecom_ShipTo_Postal_City'}","ship_country","form_data{'PO'}",
"$form_data{'Comments'}") {
$$variable =~ s/\</\&lt;/g;

$form_data{$variable} =~ .....
 
T

Tad McClellan

Marshall Dudley said:
Jürgen Exner wrote:
I have been notified that I have clean up all my variables
that print to not allow any <, >, ', &, ( or ) in them
So I wanted to have a list of the
variable names, and use one small section of code to do the
substitutions, like this:

foreach my $variable
(customer_number,"form_data{'Ecom_BillTo_Postal_Name_First'}","form_data{'Ecom_BillTo_Postal_Name_Last'}",
"form_data{'Ecom_BillTo_Company'}","form_data{'Ecom_BillTo_Postal_Street_Line1'}","form_data{'Ecom_BillTo_Postal_City'}",
"form_data{'Ecom_BillTo_Postal_StateProv'}","form_data{'Ecom_BillTo_PostalCode'}","bill_country,form_data{'Ecom_BillTo_Telecom_Phon
"form_data{'Ecom_BillTo_Online_Email'}","form_data{'Ecom_ShipTo_Postal_Name_First'}","form_data{'Ecom_ShipTo_Postal_Name_Last'}",
"form_data{'Ecom_ShipTo_Postal_Street_Line1'}","form_data{'Ecom_ShipTo_Postal_City'}","ship_country","form_data{'PO'}",
"$form_data{'Comments'}") {
$$variable =~ s/\</\&lt;/g;
$$variable =~ s/\>/\&gt;/g;
$$variable =~ s/\(/\(/g;
$$variable =~ s/\)/\)/g;
$$variable =~ s/\'/\'/g;
}


Do you need a bazillion hash entries to illustrate your problem,
or would, say, two entries do it?

Do you need 5 substitutions to illustrate your problem, or would, say,
one or two substitutions do it?

Have you seen the Posting Guidelines that are posted here frequently?

The

< > ' &

characters are not meta there, so they do not need any backslashing.

If I inline it, I end up with 5*18 or 90 lines of code in what should be
able to be done in 6 or 7.


Now that you have come clean on your XY problem, we can offer a fairly
easy solution that uses no crufty symbolic references.

Use the aliasing feature of foreach instead:

-------------------------------------------------
#!/usr/bin/perl
use warnings;
use strict;

my $customer_number = '<bad stuff>';

my %form_data = (
abc => 'more <bad> stuff',
xyz => 'yet more <ungood> stuff',
);

foreach my $var ( $customer_number, values %form_data ) {
$var =~ s/</&lt;/g;
$var =~ s/>/&gt;/g;
}

print "customer_number=$customer_number\n";
print "$_=$form_data{$_}\n" for keys %form_data;
 
M

Marshall Dudley

Uri said:
MD> I looked at the faq, but did not really see anything applicable. Here
MD> is the deal. I have been notified that I have clean up all my
MD> variables that print to not allow any <, >, ', &, ( or ) in them to
MD> prevent cross platform scripting hacking. So I have a confirmation
MD> page that prints dozens of variables that are global variables, most
MD> of which are form variables from the form input. So I wanted to have
MD> a list of the variable names, and use one small section of code to do
MD> the substitutions, like this:

you are thinking about this in a totally backwards way on several levels.

MD> foreach my $variable
MD> (customer_number,"form_data{'Ecom_BillTo_Postal_Name_First'}","form_data{'Ecom_BillTo_Postal_Name_Last'}",
MD> "form_data{'Ecom_BillTo_Company'}","form_data{'Ecom_BillTo_Postal_S

where did those 'variables' come from? show that code too. and as
several people have said, "form_data{'Ecom_BillTo_Postal_Name_First'}"
IS NOT A VARIABLE. it is not even a hash value as it has no normal perl
$hash{key} syntax (it is missing the leading $).

&require_supporting_libraries (__FILE__,__LINE__,"library/cgi-lib.pl");
&ReadParse(*form_data);
i don't know what you
think it is nor where you learned it but it makes no sense in how you
describe it. it is a simple string expression. so it can't ever refer to
anything else in perl especially other 'variables' as it is not even a
proper variable name.
$form_data{'string'} is a standard hash variable name. I am not sure
why you think it is not.
now you actually seem to have the values in a hash. i will assume that
the hash is named %form_data since it is perl. maybe it comes from some
bastard cgi parser (my main guess). so the first thing you need to do is
use a proper module CGI.pm to get your form params.
I am using the cgi-lib.pl library routine to get them.
but let's stick with
the hash for now and this is easily changed to use CGI.pm.


MD> $$variable =~ s/\</\&lt;/g;
MD> $$variable =~ s/\>/\&gt;/g;
MD> $$variable =~ s/\(/\(/g;
MD> $$variable =~ s/\)/\)/g;
MD> $$variable =~ s/\'/\'/g;

again, perl has modules for that. why are you reinventing wheels?


MD> If I inline it, I end up with 5*18 or 90 lines of code in what should
MD> be able to be done in 6 or 7.

if you used a module it would be 1 line.

use HTML::Entities

encode_entities $_ for values %form_data ;
OK, I will check the Entities module.

Thanks,

Marshall
 
U

Uri Guttman

MD> Uri Guttman wrote:

MD> &require_supporting_libraries
MD> (__FILE__,__LINE__,"library/cgi-lib.pl");


where did that sub come from? do you really need to know the line and
file where you loaded something? if an error happened, perl will tell
you that info.

MD> &ReadParse(*form_data);

that is an ancient, buggy and crappy cgi library. use CGI.pm and it even
has a compatible function for you.
MD> $form_data{'string'} is a standard hash variable name. I am not sure
MD> why you think it is not.

because of what i said. YOU WERE MISSING THE LEADING $ when you
(mis)used it in your loop. THAT was a string and not a variable. anyhow
you can't do symrefs like that even if you wanted to (which you don't.

MD> I am using the cgi-lib.pl library routine to get them.

use CGI.pm. cgi-lib hasn't been touched in over a decade.

MD> If I inline it, I end up with 5*18 or 90 lines of code in what should
MD> be able to be done in 6 or 7.MD> OK, I will check the Entities module.

and CGI.pm and learn some basic perl. your concept of a loop over a hash
was nowhere close to what you wanted.

uri
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top