File handle Variable scope issue

T

Truthless

Hello All,

I am somewhat new to perl and I am having some difficulty with a cgi
script that I am making. This script is supposed to read a html file and
replace certain sections of it with its own variables.

Code similar to this works great. as long as $html is in the actual script.

$variables = "Hello World";
$html = '<h1>'.$variables.'</h1>';

sub print_html {
print "Content-type:text/html\n\n";
print <<End_of_Bottom;
$html
End_of_Bottom
}

This outputs <h1>Hello World</h1>.

The issue I am having is getting the $variables to be parsed if the html
is pulled from a file. As I am doing here...

$confile = 'myfile.html'; #file with <h1>$variables</h1> in it

sub openconf {
open(content,"$confile") or dienice("Cant open $confile : $!");
@ary = <content>;
close(content);
foreach $line (@ary) {
chomp($line);
print "$line\n";
}
}

This will print <h1>$variables</h1>, rather than the desired <h1>Hello
World</h1>.

Could any of you please tell me what I can do to make the variables in
the strings that come from the file handle actually evaluate? There must
be something basic I am looking for.

Thank you for any help.


T.
 
R

Ragnar Hafstað

[snipped why are not variables like here-documents]
Could any of you please tell me what I can do to make the variables in
the strings that come from the file handle actually evaluate? There must
be something basic I am looking for.

yes to make the variables actually *evaluate*, you could use *eval*

this is discussed in fact in the FAQ:
perldoc -q "How can I expand variables in text strings"

personally I prefer to use a hash:

$subs=(a=>'b', foo=>'bar');
$text='some text containing easily matched markers like %a% or %foo%';
$text=~s/%(\w+)%/$subs{$1}/g;

this way, $text can safely be read from a file that others can modify, even
if i dont trust them
not to put something nasty in it.

gnari
 
R

Ragnar Hafstað

[snipped variable expantion puzzle]

wierd choice of Subject line, by the way.

gnari
 
T

Tad McClellan

Truthless said:
This script is supposed to read a html file and
replace certain sections of it with its own variables.


There are plenty of already designed, implemented, tested and
supported templating systems.

I'd use one of those rather than invent yet another one...

You don't need to do this. It has already been done (repeatedly).

The issue I am having is getting the $variables to be parsed if the html
is pulled from a file. As I am doing here...

open(content,"$confile") or dienice("Cant open $confile : $!");


That will break when the Next Version of Perl introduces a
new function named content().

You should use UPPER CASE for filehandles.

You also have a useless use of double quotes, see the Perl FAQ:

What's wrong with always quoting "$vars"?


open(CONTENT, $confile) or dienice("Cant open '$confile' : $!");

@ary = <content>;

There must
be something basic I am looking for.


Lookup the $/ variable in perlvar.pod.

Enable slurp mode.
 
T

Truthless

Iain said:


Thanks, but I still have questions.
I read that link and what I could take from it I've tried to use.

$var = "Hello World";
sub openconf {
local( $/, *CONF ) ;
open(CONF,$confile) or dienice("Cant open $confile : $!");
$text = <CONF>
}
print "$text";

The trouble is that
print "$text"; gives me the literal strings from the file and goes not
expand the variables within. I still get <h1>$var</h1>. I am not certain
what is needed to make it display <h1>Hello World</h1> The perldocs are
very good but I think I need an example. I see a lot of the docs have
regex or something like this $text =~ s/(\$\w+)/$1/eeg; I am not certain
what direction I should be going here. If I plant $vars in any
other type of string variable it works great.

$var = "Hello World";
$text = "This is a string of text $var";
print "$text";


The above outputs


This is a string of text Hello World.

Why is it that when the string of text comes from a file handle it does
not expand? What can I do to make it expand properly?

Thank you.
 
T

Truthless

Tad said:
There are plenty of already designed, implemented, tested and
supported templating systems.

I'd use one of those rather than invent yet another one...

You don't need to do this. It has already been done (repeatedly).

That won't help me learn CGI :)
Lookup the $/ variable in perlvar.pod.

Enable slurp mode.

I think I have the slurp down but the variables do not expand.

sub openconf {
local( $/, *CONF ) ;
open(CONF,$confile) or dienice("Cant open $confile : $!");
$text = <CONF>
}


Any ideas. The perldocs are very complete but a little much I just need
an example.

Thanks in advance.

T
 
T

Truthless

But that is an example! Why don't you try it in your code?
$text = 'This is a string of text $var';
------------^-----------------------------^

you notice a difference. You need to understand the difference between
a literal and an interpolated string, i.e. the difference between
using single-quotes and double-quotes when quoting a string.
Hello,

sub openconf {
local( $/, *CONF ) ;
open(CONF,$confile) or dienice("Cant open $confile : $!");
$text = <CONF>;
$text =~ s/(\$\w+)/$1/eeg;
}


The $text =~ s/(\$\w+)/$1/eeg; trick worked but I am not certain what it
is doing exactly. Is it regex that simply looks for $anything ? I guess
I need to learn more regex.
Double quotes and single quotes as with many scripting languages are the
same. Usually " means interpret and ' means literally. I had more than
one response mention the quotes, I was not sure exactly what the quoting
issue was since I WAS using " and I wanted variables expanded.

Thanks for the sugestion,
perhaps some one could parphrase the
$text =~ s/(\$\w+)/$1/eeg; assignment for me.

TIA,
 
G

Gunnar Hjalmarsson

Truthless said:
The trouble is that print "$text"; gives me the literal strings
from the file and goes not expand the variables within. I still get
<h1>$var</h1>.

The perldocs are very good but I think I need an example. I see a
lot of the docs have regex or something like this
$text =~ s/(\$\w+)/$1/eeg;

But that is an example! Why don't you try it in your code?
If I plant $vars in any other type of string variable it works
great.

$var = "Hello World";
$text = "This is a string of text $var";
print "$text";

But if you do:

$text = 'This is a string of text $var';
------------^-----------------------------^

you notice a difference. You need to understand the difference between
a literal and an interpolated string, i.e. the difference between
using single-quotes and double-quotes when quoting a string.

http://www.perldoc.com/perl5.8.0/pod/perlintro.html#Basic-syntax-overview

When you read data from a file, nothing gets interpolated, so it is
similar to using single-quotes, so to say.
 
G

Gregory Toomey

It was a dark and stormy night, and Truthless managed to scribble:
Hello All,

I am somewhat new to perl and I am having some difficulty with a cgi
script that I am making. This script is supposed to read a html file and
replace certain sections of it with its own variables.

Code similar to this works great. as long as $html is in the actual
script.

$variables = "Hello World";
$html = '<h1>'.$variables.'</h1>';

sub print_html {
print "Content-type:text/html\n\n";
print <<End_of_Bottom;
$html
End_of_Bottom
}

This outputs <h1>Hello World</h1>.

The issue I am having is getting the $variables to be parsed if the html
is pulled from a file. As I am doing here...

$confile = 'myfile.html'; #file with <h1>$variables</h1> in it

sub openconf {
open(content,"$confile") or dienice("Cant open $confile : $!");
@ary = <content>;
close(content);
foreach $line (@ary) {
chomp($line);
print "$line\n";
}
}

This will print <h1>$variables</h1>, rather than the desired <h1>Hello
World</h1>.

Could any of you please tell me what I can do to make the variables in
the strings that come from the file handle actually evaluate? There must
be something basic I am looking for.

Thank you for any help.

Err, yes. Your brain was at there I was at about 3 years ago. You can use Perl templates but there's nothing like getting your hands dirty!

Here's the Rolls Royce version of what you want:



open(INFILE, 'myfile.htm');
foreach (<INFILE>) {
s/(\$\w+:):\w+)?)/$1/eeg;
print;
}

WARNING: because this does command substitution and evaluation, it can there are security issues and is dangerous in the wrong hands.

This works with lexical variables like $var. It also works with package variables like $var1::var2.


Another question you will soon ask youself is "well if I can evaluate a variable, can I evaluate a function/subroutine." The answer is yes, providing you provide a return value & use the weird Perl syntax @{[subroutine_name()]}

EXAMPLE: define a subroutine testsub in your main program

sub testsub {return "This could be anything" }

Then myfile.html could contain the following 3 lines:
Hello World
@{[testsub()]}
Line 3


gtoomey


gtoomey
 
G

Gunnar Hjalmarsson

Truthless said:
sub openconf {
local( $/, *CONF ) ;
open(CONF,$confile) or dienice("Cant open $confile : $!");
$text = <CONF>;
$text =~ s/(\$\w+)/$1/eeg;
}

The $text =~ s/(\$\w+)/$1/eeg; trick worked but I am not certain
what it is doing exactly. Is it regex that simply looks for
$anything ?

It's more than a regex.

http://www.perldoc.com/perl5.8.0/pod/perlop.html#s-PATTERN-REPLACEMENT-egimosx

Most is explained there, except for the actual regex part of it.

The PATTERN, i.e. /(\$\w+)/, consists of a regex that matches a '$'
character followed by one or more word characters. The parentheses
capture the matched substring into a capture buffer, which is referred
to in REPLACEMENT through the special $1 variable.
I guess I need to learn more regex.

Don't we all. ;-)

http://www.perldoc.com/perl5.8.0/pod/perlre.html
 
T

Tore Aursand

That won't help me learn CGI :)

Yes, it does; You - as a programmer - can focus on the functionality of
your scripts/applications, rather then being hung up in details about
separating code from design (which I think this is all about).

Take a look at HTML::Template [1]. I think it does excactly what you
need, and it doesn't let you "forget about" learning CGI programming, as
separating code from design has nothing to do with CGI.

[1] Just an example; There are many other templating modules out there,
and a search for 'template' on <http://www.cpan.org/> will help you out
choosing the right one.
 
T

Tad McClellan

Truthless said:
That won't help me learn CGI :)


We usually assume that questions asked here are for Real Programs.

If you are doing it for a learning exercise, then you should say so,
else we are likely to apply Software Engineering to your problem.

I have the slurp down but the variables do not expand. ^^^^^^
^^^^^^
Any ideas.


perldoc -q expand

How can I expand variables in text strings?

The perldocs are very complete but a little much


We could help you understand them if you told us what part(s) it
is that you are having trouble with...
 
B

Brian McCauley

We usually assume that questions asked here are for Real Programs.

If you are doing it for a learning exercise, then you should say so,
else we are likely to apply Software Engineering to your problem.




perldoc -q expand

How can I expand variables in text strings?

Take note, the FAQ doesn't tell you the simple answer because the FAQ
maintainers assume people are too dumb to know when it is safe to apply
the simple answer.

The FAQ, in effect, tells you to roll your own simple templating
system.

You can, however use one of Perl's built-in templating systems (string
interpolation).

chop ( my $expanded = eval "<<__EOL__\n$string\n__EOL__" );
die $@ if $@;

This, of course, gives the author of the data in $string the ability
to execute arbitrary code. Often this is a very bad thing (when they
are not trusted). On the other hand often it is a very good thing
(when you want a full-featured templating system).

It is true that some people are dumb enough to use this even when it
is a bad thing. However, refusing to put the eval solution in the FAQ
(with suitable warnings) won't protect them. Refusing to put the
simple answer in the FAQ means that:

People will use the clumsy (roll-your-own templating system)
solution even when the simple (eval) one is applicable.

As people need more fancy templating features their hand-rolled
templating systems will grow.

When people discover the simple solution (for themselves or from
other sources) they may not be warned of the dangers.

When people discover the simple solution they will loose faith in
the FAQ.

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 

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

Forum statistics

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

Latest Threads

Top