use external files as "HERE-docs" (and avoid the undefined substitions)

D

dede

Hello friends of the community,

find below the solution I am currently using to load external
text-files that
are seamlessly interpolated to behave like the useful HERE-docs:

echo <<"EOT";
Hello $strWorld ...
EOT

SNIPPET:

while (<$handle>) {
$_ =~ s/(\$\S+)/defined eval($1) ? eval($1) : $1/gsxe;
#interpolate all $vars or $self->vars etc.
#note that this "old test"...
#$_ =~ s/(\$\w+)/defined $1 ? $1 : "undefined"/gsxee;
#produced the notorious "undefined substitution errors"

#here might be some extra cleanup-work of the file

push @lines, $_;
} #each line;
close $handle;

A.
Note that you can substitute ANY var or OO-pseudo hash-var (ie.
inst-var)
from the namespace of the context (function/method) that this snippet
resides in.
B.
You might also be more specific and include some static text in the
search
pattern and then add some .. eval('whatever'.$1.'foo') .. stuff.
C.
Note that the defined eval (...) is necessary in order to return values
that
Perls likes to interpret as FALSE (eg. '' or 0).

Any comments / immprovements are welcome.
Share and Enjoy :)

dede, Paris / France
 
T

Tad McClellan

dede said:
find below the solution I am currently using to load external
text-files that
are seamlessly interpolated to behave like the useful HERE-docs:


What is wrong with making the external files be Real Perl Code,
and then simply require()ing them?

$_ =~ s/(\$\S+)/defined eval($1) ? eval($1) : $1/gsxe;


The s///s modifier affects only dot, it is a no-op when the
pattern does not contain a dot. You should not add modifiers
willy nilly, add them only when you _need_ them.

The s///x modifier allows whitespace and comments in the pattern,
it is a no-op when there is no whitespace nor comments in
the pattern (more willy-nillyness).

Where are these mysterious "text files" coming from?

Consider what your code will do with file contents like:

$foo;unlink(<*>)

for instance.

#$_ =~ s/(\$\w+)/defined $1 ? $1 : "undefined"/gsxee;
#produced the notorious "undefined substitution errors"


It is not "notorious", it is "fictional". :)

What message is it that you are really referring to?

Does the message appear in perldiag.pod? I can't find it...
 
D

dede

Thanks for your remark, Paul

actually, yes , i assumed that there is always a whitespace delimiting
the end of the string, since I wanted to be as close to the "normal"
way of identifying variables as possible.
We might change to ..... s/(\${.+})/ defined eval ...... to force the
curly brackets as "tidy" syntax in the external file (that i use to
build HTMLs - see other reply).
This would protect us against "accidents" like wrong evals of
$something and enhance (slightly) the performance due to the not-made
eval's.
what do you think?

dede
 
D

dede

Salut Tad,
thank you 4 your helpful remarks.

a) Require ?
Uh, i was not clear on this one. I actually "scan" the external files
like SQL-scripts or HTML-templates to get these "dynamic" - a bit like
using JSP-variables or PHP-vars. Soon I'd like to publish a
Pod-HTML-site generator that uses this technique.

b) Unnecessary modifiers !
Yeah - you are right. A nasty side effect of doing copy&paste, or
"willy-nilly" programming as you might put it. Acknowledged.

c) Errors?
Hmmm ... again .. 1st think then post - shame on me.
The error is actually called
"Use of uninitialized value in substitution iterator at
config/Scanner.pm line 501" (freshly generated today with Perl 5.8.4.
Activestate)

Merci again,
dede
 
B

Brian McCauley

dede said:
Hello friends of the community,

find below the solution I am currently using to load external
text-files that
are seamlessly interpolated to behave like the useful HERE-docs:

echo <<"EOT";
Hello $strWorld ...
EOT

SNIPPET:

while (<$handle>) {
$_ =~ s/(\$\S+)/defined eval($1) ? eval($1) : $1/gsxe;

This is unduely messy and complicated.

By using \S+ you expose yourself to all the dangers of eval().

By not using a single eval() of a here-doc you make the syntax of the
files unnecessarily un-Perl like.

If you have already accepted all the costs of using eval() you may as
well get all the beniefit.

my $text = do { local $/; <$handle> };
chop ( $text = eval "<<__END__\n$text\n__END__" );

This, of course, assumes that you can reasonably slurp the whole file.

Although as Tad points out it may be better simply to make the files
real Perl files and do() or require() them.

I should add that you may even want to make the template be the actual
Perl scripts and make them use your module.
Note that the defined eval (...) is necessary in order to return values
that Perls likes to interpret as FALSE (eg. '' or 0).

Why not simply switch off the warning?
Any comments / immprovements are welcome.

You are inventing yet another templating system.

Perl already has two built-in templating systems (here-docs and formats)
and others on CPAN. You should think hard before you invent another.
 
A

A. Sinan Unur

c) Errors?

Dunno. Please quote the part of the post you are replying to and place
your replies below the original text. That way, people other than you can
figure out what you are replying to.
Hmmm ... again .. 1st think then post - shame on me.
Exactly.

The error is actually called
"Use of uninitialized value in substitution iterator at

That is a warning.

Try

use diagnostics;

to get more information.
 

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

Staff online

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top