Re: How to use __DATA__ efficiently, help!
by Your Mother (Archbishop) on Feb 09, 2011 at 21:11 UTC
|
What Tommy just said. This the Wrong Way™ to do it. That said, I do exactly this sometimes with Template by using named blocks. Here's a runnable example-
use warnings;
use strict;
use Template;
use CGI qw( header );
print header();
my $tt2 = Template->new( TRIM => 1 );
my @actions = qw( foo bar );
my @titles = ( "O HAI", "O NOES", "KTHXBAI" );
$tt2->process(\*DATA,
{ title => $titles[rand@titles],
my_action => $actions[rand @actions],
})
or warn $tt2->error;
__DATA__
[%~BLOCK foo %]
This is my foo. There are many foos like it but this one is mine.
[%~END %]
[%~BLOCK bar %]
This is my barbaz. This is my qux. This is for coding, this is for...
+uh...
[%~END %]
[%~# TEMPLATE ----------%]
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /
+>
<title>[% title | html %]</title>
</head>
<body>
<header>
<h1>[% title | html %]</h1>
</header>
<article>
[% PROCESS $my_action %]
<aside>Action: [% my_action | html %]</aside>
</article>
<footer>
<small>
License: <a itemprop="license"
href="http://perlfoundation.org/artistic_license_2_0">Artistic 2.0</a
+>
</small>
</footer>
</body>
</html>
| [reply] [d/l] |
Re: How to use __DATA__ efficiently, help!
by ELISHEVA (Prior) on Feb 09, 2011 at 20:02 UTC
|
my @aData;
{
#set the record divider to __DATA__ :-)
local $/='__DATA__';
@aData = <DATA>;
chomp @aData; #get rid of __DATA__ from end of record
}
print STDERR "------------DATA #1 ----------------\n$aData[0]"
. "------------DATA #2 ----------------\n$aData[1]";
outputs
| [reply] [d/l] [select] |
|
Would this be easier if it was done using HTML::Template? Has anyone done such using this method?
| [reply] |
|
my $date='**2010-02-09**';
my $line = $aData[0];
$line =~ s/\$date/$date/g;
print STDERR "------------DATA #1 ----------------\n$line";
$date='**1910-02-09**';
$line = $aData[0];
$line =~ s/\$date/$date/g;
print STDERR "------------DATA #2 ----------------\n$line";
However, it won't scale well. It will quickly become difficult to manage. Furthermore, the more variables the more likely you are going to have some random unintended substitutions. At that point you would be very wise to use a module like HTML::Template. Think of it as your solution with all the problems and corner cases debugged for you in advance.
| [reply] [d/l] [select] |
Re: How to use __DATA__ efficiently, help!
by Tommy (Chaplain) on Feb 09, 2011 at 21:08 UTC
|
You're going to quickly outgrow this method of generating html output from logically calculated values. Interspersing code with content is good for the quick and dirty jobs, but it won't work out very well for you at all as you continue to grow your code and improve upon it.
I invite you to consider a templating engine, such as Template::Toolkit or others mentioned already in response to your question. There is a slight learning curve, but I can assure you with almost complete certainty that once you get to the point where you are actively using and deriving benefit from a templating solution that allows for the separation of code and content, you will won't ever go back to the more primitive and less elegant practice of doing otherwise.
| [reply] |
Re: How to use __DATA__ efficiently, help!
by CountZero (Bishop) on Feb 09, 2011 at 19:07 UTC
|
Data::Section will give you the possibility to access multiple sections in your __DATA__ area.The unitialized value warning (it is not an error message, just a warning only) is probably because you have empty lines in your __DATA__ area. I wouldn't worry about it too much.
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James
| [reply] [d/l] [select] |
|
it is not an error message
He made an error (concatenated two variable without giving either a value) and Perl issued a message in response to that error. How is that message not an error message? It's simply not an (immediately) fatal error.
is probably because you have empty lines in your __DATA__ area.
No, he gets the warning before even executing <DATA> because he's using a bottom tested loop.
| [reply] [d/l] |
|
He made an error (concatenated two variable without giving either a value) and Perl issued a message in response to that error. Then we have different definitions of error and warning. The OP concatenated nothing to nothing (and thus wastes a cycle of that loop) but his output is still correct. In my book that is not an error, but it does warrant a warning as it can be written better.
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James
| [reply] |
|
Re: How to use __DATA__ efficiently, help!
by bart (Canon) on Feb 09, 2011 at 21:14 UTC
|
Split the DATA section into 2 parts? I think that's better done using here-docs. Granted, the strings will be intertwined in between the chunks of Perl code instead of at the end, but that doesn't have to be a disadvantage; especially with lots and lots of html snippets. I think having to count in order to know what string you're using where is a bad situation as soon as it is no longer trivial.
And perhaps you should reconsider using a templating system, for example, Template Toolkit. At least the html data will be organized by the page layout, and not by the code flow — which can be like spaghetti code, if you want to follow how a page is built. | [reply] |
Re: How to use __DATA__ efficiently, help!
by shawnhcorey (Friar) on Feb 09, 2011 at 19:50 UTC
|
my $data = ''; # set to the empty string
do{ $data = $data . $_ } while (<DATA>);
Always initialize your variables. | [reply] |
|
Actually, that wouldn't help here, as it's not the undefined $data that Perl is complaining about, but the undefined $_.
| [reply] [d/l] [select] |
Re: How to use __DATA__ efficiently, help!
by PyrexKidd (Monk) on Feb 10, 2011 at 01:33 UTC
|
I agree with the other commenter. HTML::Template would be ideal for your situation. Additionally this allow you to abstract the HTML from your perl code and focus on the perl in your perl scripts. IMHO it is more readable to have your data in separate files.
Something like this:
#!/usr/bin/perl
use strict;
use warnings;
my $TEMPLATE_PATH = "/some/path/";
my $template_name = "data.tmpl"
my $tmpl = new HTML::Template(
path => [ "$TEMPLATE_PATH", ],
filename => "$template_name",
die_on_bad_params => 0,
);
$tmpl->params( data1 => 'true', );
open my $OUTPUT, '>', \my $output;
print $OUTPUT $tmpl->output();
close $OUTPUT;
print $string, "\n";
tmplate1.tmpl:
<tmple_if name'data1'>
<table width="100%" border="0" bgcolor="#ffffff" cellpadding="0"
+cellspacing="0">
<tr>
<td colspan="2"> </td>
</tr>
<tr>
<td width="60%">All Names List from:</td>
<td width="40%" align="left"><b>$date</b></td>
</tr>
<tr>
<td width="100%" colspan="2"> </td>
</tr>
</table>
</tmpl_if>
<tmpl_if name='data2'>
<table width="100%" border="0" bgcolor="#ffffff" cellpadding="0" cel
+lspacing="2">
<tr>
<td><b>Name</b></td>
<td><b>Address</b></td>
<td><b>Phone</b></td>
<td><b>Email</b></td>
<td><b>$location</b></td>
</tr>
<tr>
<td colspan="5"> </td>
</tr>
</tmpl_it>
You can obviously tailor this more to specifically suit your needs.
| [reply] [d/l] [select] |
|
Thank you all, thats the way to go!
| [reply] |
Re: How to use __DATA__ efficiently, help!
by Anonyrnous Monk (Hermit) on Feb 09, 2011 at 19:14 UTC
|
#do{$data = $data . $_ } while (<DATA>); #gives a uninitialized value
+in concatenation
You get the "uninitialized value" warning because the do {...} executes once before a value is being assigned to $_. Just turn it around:
my $data;
while (<DATA>) { $data .= $_ }
BTW, note that $data .= "foo" (or $data = $data . "foo" for that matter) is a special case that does not generate an "uninitialzed value" warning, even if $data is undefined initially:
$ perl -we 'my $foo; $foo = $foo . "foo"' # no warning
while this does, of course:
$ perl -we 'my $foo; my $bar = $foo . "foo"'
Use of uninitialized value $foo in concatenation (.) or string at -e l
+ine 1.
| [reply] [d/l] [select] |
|
I found a way to " values of variables ($date - $location) into the html inside the "__DATA__"".
I can do this, just hope I am not breaking any rules:
while (<DATA>) {
$_.=s/<--date\/\/>/$date/;
$_.=s/<--loc\/\/>/$location/;
$data .= $_
}
But how to use multiple sets of "__DATA__" still stands. | [reply] [d/l] |
|
But how to use multiple sets of "__DATA__" still stands.
The answer is simple: you can't. There's only one __DATA__ section. At least in the main package.
In other words, you'd have to use some separator, e.g. an empty line (if that doesn't occur otherwise in the data), and then split it up into sets yourself.
You could in theory put different __DATA__ sections in different modules (i.e. different packages in different files), and then access them as Foo::DATA, etc., but you might as well just put the data sets in normal files and read them from there...
# File Set1.pm
package Set1;
1;
__DATA__
foo1
foo2
foo3
# File Set2.pm
package Set2;
1;
__DATA__
bar1
bar2
bar3
# main script
#!/usr/bin/perl -w
use strict;
use Set1;
use Set2;
print "Set 1:\n";
while (<Set1::DATA>) { print }
print "Set 2:\n";
while (<Set2::DATA>) { print }
Output:
Set 1:
foo1
foo2
foo3
Set 2:
bar1
bar2
bar3
| [reply] [d/l] [select] |
|
|
|
I am getting weird numbers in the middle of the html code; 1 and 11, using:
while (<DATA>) {
$_.=s/<--date\/\/>/$date/;
$_.=s/<--loc\/\/>/$location/;
$data .= $_
}
Any ideas why? | [reply] [d/l] |
|