Beginners Program

L

Lenny Challis

Good evening everyone.

I am currently in college doing a National Diploma in computing. Most of the
guys there haven't studied HTML or CSS or the likes and next year I think
they may be asking us to do ASP. I'm not very fond of the idea at all, so I
thought I would code my first assignment in Perl.

I had to work with 2 friends however and they have never seen perl, or even
heard of it. In fact, the looks on peoples faces when I did a presentation
on Larry Wall and Perl were kind of strange to say the least.

Anyway, to the point. I am quite new to perl myself, but I absolutely adore
it already. I am very keen to learn and make good habits from the very
beginning. I hope you don't mind, but here is a program I have made in Perl
to convert HTML files into CGI. I will use this while working with my
friends.

I would love to accept any criticism's. It is one of my first programs, but
don't miss anything. One thing I hate is getting into bad habits, so I would
like to pick them up now.

Anyway, here goes.
Thanks alot,
Lenny Challis.

___________________________

#!/usr/bin/perl -w

#this program takes in the input (html) file as command lines first argument
and output cgi file as second

use strict;

my $ofile = shift @ARGV;
my $cfile = shift @ARGV; #get the two filenames

open INPUT, "<", $ofile or die "Can't open $ofile: $!\n";
open OUTPUT, ">", $cfile or die "Can't open $cfile: $!\n"; #open
both files

print OUTPUT "\#!/usr/bin/perl\n\n";
print OUTPUT "print \"Content-type:text/html\\n\\n\";\n"; #print
the shebang and content tags

while (<INPUT>)
{
chomp($_); #getting rid of the \n's makes the code
alot more understandable
$_ =~ s/"/\\"/g; #first, escape
all quotes
$_ = "print \"" . $_ . "\\n\";\n"; #add print function
and newlines to $_
print OUTPUT $_; #add line to the output
file
}

print "Completed."; #let them know its
done

_____________________________

I am looking into getting in CGI and want to also get into mod_perl in the
future.

Thanks alot for your time.
 
B

Bob Walton

Lenny said:
Good evening everyone.

I am currently in college doing a National Diploma in computing. Most of the
guys there haven't studied HTML or CSS or the likes and next year I think
they may be asking us to do ASP. I'm not very fond of the idea at all, so I
thought I would code my first assignment in Perl.

Excellent choice IMHO.

I had to work with 2 friends however and they have never seen perl, or even

----------------------------------------------------------------^
The official correct name of the language is Perl.

heard of it. In fact, the looks on peoples faces when I did a presentation
on Larry Wall and Perl were kind of strange to say the least.

Anyway, to the point. I am quite new to perl myself, but I absolutely adore
it already. I am very keen to learn and make good habits from the very
beginning. I hope you don't mind, but here is a program I have made in Perl
to convert HTML files into CGI. I will use this while working with my
friends.

I would love to accept any criticism's. It is one of my first programs, but
don't miss anything. One thing I hate is getting into bad habits, so I would
like to pick them up now.

Anyway, here goes.
Thanks alot,
Lenny Challis.

___________________________

#!/usr/bin/perl -w
------------------^^
Excellent!



#this program takes in the input (html) file as command lines first argument
and output cgi file as second

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Commentary wrapped somewhere between your posting and my reading. Try
to avoid posting commentary (or code) which wraps.

use strict;
--^^^^^^^^^^
Outstanding!



my $ofile = shift @ARGV;
my $cfile = shift @ARGV; #get the two filenames

open INPUT, "<", $ofile or die "Can't open $ofile: $!\n";
open OUTPUT, ">", $cfile or die "Can't open $cfile: $!\n"; #open
both files

print OUTPUT "\#!/usr/bin/perl\n\n";

----------------^
It is not necessary to escape a # character in a qq() string.

print OUTPUT "print \"Content-type:text/html\\n\\n\";\n"; #print
the shebang and content tags

while (<INPUT>)
{
chomp($_); #getting rid of the \n's makes the code

--^-----^^
It is usually good style to indent the bodies of loops by four
characters. Makes it much more readable.

Also, $_ is the default argument to chomp, so you can say just:

chomp;

Likewise $_ can be omitted in many other places, like the next
statement, which could be just s/"/\\"/g; . That is usually the Perlish
thing to do.

alot more understandable
$_ =~ s/"/\\"/g; #first, escape
all quotes
$_ = "print \"" . $_ . "\\n\";\n"; #add print function

-----------------^^^^^^^^
Here you could "interpolate" $_ into the string, as in:

$_ = "print \"$_\\n\";\n";

Any scalar variable appearing in a "-string is substituted into the
string, so:

$v='y';
print "x $v z\n";

prints

x y z

That is why there are "-strings in addition to '-strings, and why they
aren't the same.
and newlines to $_
print OUTPUT $_; #add line to the output
file
}

print "Completed."; #let them know its

-------------------^
Depending on your OS, you might want a \n at the end of this string to
avoid having a command prompt following the output on the same line.

done

_____________________________

I am looking into getting in CGI and want to also get into mod_perl in the
future.

Thanks alot for your time.


You're welcome. Looks to me like you did a fine job on your Perl
program. Hope you find Perl as fascinating and useful as I do.
 
M

Matt Garrish

Lenny Challis said:
#!/usr/bin/perl -w

#this program takes in the input (html) file as command lines first argument
and output cgi file as second

use strict;

Very nice beginning.
my $ofile = shift @ARGV;
my $cfile = shift @ARGV; #get the two filenames

unless (scalar(@ARGV) == 2) {

die "Correct usage: perl myscript.pl input_file output_file\n";

}

my ($ofile, $cfile) = @ARGV;

You're better off checking your arguments before you try processing them.
Saves the user having to guess why the script might not be running. Also,
strange names for an input file and output file. It might make more sense to
call them $infile and $outfile so you don't confuse yourself later on. It
also helps when you have to come back to your code somewhere down the line
(or when someone else does).
open INPUT, "<", $ofile or die "Can't open $ofile: $!\n";
open OUTPUT, ">", $cfile or die "Can't open $cfile: $!\n"; #open
both files

print OUTPUT "\#!/usr/bin/perl\n\n";

print OUTPUT "#!/usr/bin/perl\n\n"; # no need to escape a # within quotes
print OUTPUT "print \"Content-type:text/html\\n\\n\";\n"; #print
the shebang and content tags

print OUTPUT 'print "Content-type: text/html\n\n";' . "\n";

Don't use double-quotes unless you need them.
while (<INPUT>)

while (my $line = <INPUT>) {
....

Better to name your variables. It's okay to use $_ for a very small block,
but it's easy to forget what you're operating on and what $_ might be set
to.

Not an exhaustive review, but hope that gives you a few things to think
about.

Matt
 
L

Lenny Challis

Bob Walton Wrote:


You're welcome. Looks to me like you did a fine job on your Perl
program. Hope you find Perl as fascinating and useful as I do.

I have been practicing making the shorter scripts (ie: not having to write
$_). Also, I know all about interpolating, I jut didn't think of doing it
this way :) (TMTOWTDI!).

Theres plenty to remember but it's such a versatile language and its so much
fun to learn. I have programmed C++, Visual Basic and a couple others, Perl
is my favourite by far. I am slowly getting my head into perl mode and yes I
_am_ finding it really useful.

Thanks for the great feedback.
Lenny
 
S

Sam Holden

I would love to accept any criticism's. It is one of my first programs, but
don't miss anything. One thing I hate is getting into bad habits, so I would
like to pick them up now.

Anyway, here goes.
Thanks alot,
Lenny Challis.

___________________________

#!/usr/bin/perl -w

#this program takes in the input (html) file as command lines first argument
and output cgi file as second

use strict;

Warnings and strictures are good :)
my $ofile = shift @ARGV;
my $cfile = shift @ARGV; #get the two filenames

open INPUT, "<", $ofile or die "Can't open $ofile: $!\n";
open OUTPUT, ">", $cfile or die "Can't open $cfile: $!\n"; #open
both files

Watch your line wrapping, I realise it's probably a posting to usenet
artifact, but even so some of the following lines are far too long, in
my opinion anyway.

I'd put single quotes aroung the < and >, since they don't need
double quote features. I'd leave off the \n on the die output so
that perl will add the line number information (which may of course
not be wanted in your case).
print OUTPUT "\#!/usr/bin/perl\n\n";
print OUTPUT "print \"Content-type:text/html\\n\\n\";\n"; #print
the shebang and content tags

# isn't special and doesn't need to be escaped in a double quoted string.

Why no warnings and strictures in the generated code?

If you are putting "s in a string then it is usually best to use a different
quote character than ". Saves on the escaping, something like:

print OUTPUT 'print "Content-type:text/html\n\n";', "\n";

or if you really must have it as one string (but I'd rather avoid the
\\s):

print OUTPUT qq{print "Content-type:text/html\\n\\n";\n};
while (<INPUT>)
{
chomp($_); #getting rid of the \n's makes the code
alot more understandable
$_ =~ s/"/\\"/g; #first, escape
all quotes

If you are using $_ there is not need to mention it, just use
s/"/\\"/g, if you want to be explicit about the variable than don't
use $_, read into $line or something...
$_ = "print \"" . $_ . "\\n\";\n"; #add print function
and newlines to $_
print OUTPUT $_; #add line to the output
file

You seem to be producing an output file that is a CGI script that will
output the input file when run. However, if there are \ characters in the
input file things could go wrong.

Try running it on a file containing

\"

in it somewhere to see the problem.

And what about files containing things like:

Bananas only $1.99 a kilo, save $$. email: (e-mail address removed)

You need to escape a lot more characters than just ".

Something like (completely untested):

s/\\/\\\\/g; #this must be done first, before we add \s
s/"/\\"/g;
s/\$/\\\$/g;
s/@/\\\@/g; # I prefer \@ in the pattern, but it isn't needed
s/\t/\\t/g;
s/\r/\\r/g;
print qq{print "$_\\n";\n};

}

print "Completed."; #let them know its
done

You should close the OUTPUT file, and check for failure. After all
writes can actually fail (the disk might fill up, for example) and
it's good to check that the output file closed successfully (you could
check on all the print calls, but that would be ugly and unwarranted
in this case).

The loop could be replaced with:

print OUTPUT "print <<'HTML';\n";
print OUTPUT while (<INPUT>);
print OUTPUT "HTML\n";

Assuming the string 'HTML' isn't found on a line by itself in the input
and that the final line of input does end with a newline character.

But that probably misses the point of introducing some perl features.

As an aside, for those who might know:

Why is
print "@";
OK, but
print "$";
isn't?

To me the first should be illegal (but I'm clearly wrong).
 
G

Gunnar Hjalmarsson

Lenny said:
I would love to accept any criticism's.

Okay, these are my comments:
#!/usr/bin/perl -w

You may want to consider the lexically scoped warnings pragma before
the dynamically scoped -w switch.

#!/usr/bin/perl
use warnings;

See http://www.perldoc.com/perl5.8.0/pod/perllexwarn.html
print OUTPUT "print \"Content-type:text/html\\n\\n\";\n";

You should learn the difference between ' and ", and consider using '
sometimes to reduce the need to escape things. For instance, that line
could be written:

print OUTPUT 'print "Content-type: text/html\n\n";', "\n";

Personally I think it makes it easier to read. See
http://www.perldoc.com/perl5.8.0/pod/perlop.html#q-STRING-
while (<INPUT>)
{
chomp($_);
$_ =~ s/"/\\"/g;
$_ = "print \"" . $_ . "\\n\";\n";
print OUTPUT $_;
}

The here-document syntax is very useful when printing HTML. Those
lines could be replaced with:

print OUTPUT "print <<HTML;\n";
print OUTPUT $_ while <INPUT>;
print OUTPUT "\nHTML\n";

See http://www.perldoc.com/perl5.8.0/pod/perlop.html#<<EOF

Also, you should make it a habit to close filehandles when you no
longer need them:

close INPUT or die $!;
close OUTPUT or die $!;
I am looking into getting in CGI

When dealing with CGI, you may want to benefit from some of the tools
in the CGI.pm module. (But don't forget to learn the basics about
what's going on behind the scenes.)

http://www.perldoc.com/perl5.8.0/lib/CGI.html

Good luck!
 
L

LaDainian Tomlinson

comp.lang.perl.misc:

I would love to accept any criticism's. It is one of my first
programs, but don't miss anything. One thing I hate is getting into
bad habits, so I would like to pick them up now.

You'd like to pick up bad habits? Hmmm...
#!/usr/bin/perl -w

#this program takes in the input (html) file as command lines first
argument and output cgi file as second

# Consider cutting your comments at a reasonable length (around 80
# characters) and continuing on the next line instead of letting your
# newsreader or text editor do the wrapping for you.

Also, rather than using the -w switch, use the warnings pragma instead
(see below).
use strict;
use warnings;
my $ofile = shift @ARGV;
my $cfile = shift @ARGV; #get the two filenames

If no arguments are passed to shift(), it assumes @ARGV (or @_ in
subroutines), so either:

my $ofile = shift;
my $cfile = shift;

or

# preferred when there are many arguments
my ($ofile, $cfile) = @ARGV;
open INPUT, "<", $ofile or die "Can't open $ofile: $!\n";
open OUTPUT, ">", $cfile or die "Can't open $cfile: $!\n";
#open both files

Note that the newline at the end of your die-string supresses the
filename and line number in the error message. For such a small script,
it's not a big deal, but there's no reason to ignore it.
print OUTPUT "\#!/usr/bin/perl\n\n";
print OUTPUT "print \"Content-type:text/html\\n\\n\";\n";
#print the shebang and content tags

No need to escape '#' characters. You can also avoid interpolation
altogether by using single quotes:

print OUTPUT 'print "Content-type:text/html\n\n";', "\n";
while (<INPUT>)
{
chomp($_); #getting rid of the \n's makes the
code alot more understandable
$_ =~ s/"/\\"/g; #first,
escape all quotes
$_ = "print \"" . $_ . "\\n\";\n"; #add print
function and newlines to $_
print OUTPUT $_; #add line to the
output file
}

print "Completed."; #let them
know its done

chomp() and s/// both operate on $_ by default:

while (<INPUT>){
chomp;
s/"/\\"/g;
# ...
}

Overall it looks fine to me. I'm somewhat new as well (but not as new
as you ;-). Style-wise, though, I would suggest removing a lot of the
superfluous commenting, and make sure you indent your blocks properly.
Keep reading clpm and you can't help but learn.

Brandan L.
 
M

Matt Garrish

Sam Holden said:
As an aside, for those who might know:

Why is
print "@";
OK, but
print "$";
isn't?

$" is a predefined variable. How would you then use it in a double-quoted
string if the above were not an error?

Matt
 
L

Lenny Challis

Sam Holden said:
Warnings and strictures are good :)


Watch your line wrapping, I realise it's probably a posting to usenet
artifact, but even so some of the following lines are far too long, in
my opinion anyway.

I'd put single quotes aroung the < and >, since they don't need
double quote features. I'd leave off the \n on the die output so
that perl will add the line number information (which may of course
not be wanted in your case).


# isn't special and doesn't need to be escaped in a double quoted string.

Why no warnings and strictures in the generated code?

If you are putting "s in a string then it is usually best to use a different
quote character than ". Saves on the escaping, something like:

print OUTPUT 'print "Content-type:text/html\n\n";', "\n";

or if you really must have it as one string (but I'd rather avoid the
\\s):

print OUTPUT qq{print "Content-type:text/html\\n\\n";\n};


If you are using $_ there is not need to mention it, just use
s/"/\\"/g, if you want to be explicit about the variable than don't
use $_, read into $line or something...


You seem to be producing an output file that is a CGI script that will
output the input file when run. However, if there are \ characters in the
input file things could go wrong.

Try running it on a file containing

\"

in it somewhere to see the problem.

And what about files containing things like:

Bananas only $1.99 a kilo, save $$. email: (e-mail address removed)

You need to escape a lot more characters than just ".

Something like (completely untested):

s/\\/\\\\/g; #this must be done first, before we add \s
s/"/\\"/g;
s/\$/\\\$/g;
s/@/\\\@/g; # I prefer \@ in the pattern, but it isn't needed
s/\t/\\t/g;
s/\r/\\r/g;
print qq{print "$_\\n";\n};



You should close the OUTPUT file, and check for failure. After all
writes can actually fail (the disk might fill up, for example) and
it's good to check that the output file closed successfully (you could
check on all the print calls, but that would be ugly and unwarranted
in this case).

The loop could be replaced with:

print OUTPUT "print <<'HTML';\n";
print OUTPUT while (<INPUT>);
print OUTPUT "HTML\n";

Assuming the string 'HTML' isn't found on a line by itself in the input
and that the final line of input does end with a newline character.

But that probably misses the point of introducing some perl features.

As an aside, for those who might know:

Why is
print "@";
OK, but
print "$";
isn't?

To me the first should be illegal (but I'm clearly wrong).

That was really great feedback.
I have learnt alot from it, Thanks alot

Lenny
 
G

Gunnar Hjalmarsson

Sam said:
You need to escape a lot more characters than just ".

Something like (completely untested):

s/\\/\\\\/g; #this must be done first, before we add \s
s/"/\\"/g;
s/\$/\\\$/g;
s/@/\\\@/g; # I prefer \@ in the pattern, but it isn't needed
s/\t/\\t/g;
s/\r/\\r/g;
print qq{print "$_\\n";\n};

The loop could be replaced with:

print OUTPUT "print <<'HTML';\n";
------------------------^----^

Which is a much smarter way to deal with the need for escaping things.
 
T

Tad McClellan

[ snip 150 lines of quoting ]

That was really great feedback.


Please learn to compose followups properly.

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

Sam Holden

$" is a predefined variable. How would you then use it in a double-quoted
string if the above were not an error?

Well, on my perl (5.8.2) you can't...

print "$""; # gives an error.

Of course you can simply use:

print qq{$"};

or

print "$\""; # I'm not sure I like this one... :)


My query is why I can include a @ at the end of a qouble quoted string and
have it work as a literal @. Doing the same with a $ causes a compile error,
with perl complaining: "Final $ should be \$ or $name at ..."

I agree with the error, what I can't understand is why a trailing @ doesn't
cause the same error, after all @foo interpolates in a double quoted string
and hence the same problem should be occuring.
 
M

Matt Garrish

Sam Holden said:
Well, on my perl (5.8.2) you can't...

print "$""; # gives an error.

Of course you can simply use:

print qq{$"};

or

print "$\""; # I'm not sure I like this one... :)


My query is why I can include a @ at the end of a qouble quoted string and
have it work as a literal @. Doing the same with a $ causes a compile error,
with perl complaining: "Final $ should be \$ or $name at ..."

Sorry, that was a horribly worded last sentence on my part.. What I was
trying to get at is that $" is a variable, but @" is not. It's like using a
\ at the end of a string. To Perl, you're escaping the last quote unless you
escape the \. If you use a $ at the end of a double-quoted string, Perl sees
it (can Perl see?) as the special variable. If you use an @ at the end of a
string, however, the only thing it could be is a literal @.

Matt
 
A

Anno Siegel

Matt Garrish said:
$" is a predefined variable. How would you then use it in a double-quoted
string if the above were not an error?

So is @" (though Perl doesn't use it), that's not the point.

Perl treats interpolation of arrays differently than interpolation of
scalars. Array interpolation was introduced rather late in the game.
To make the transition as smooth as possible, Perl treats "@" in a string
as a normal character whenever possible. The rather complex handling of
"$" was already in place at the time and was, of course, not changed.

So there really is no good reason for the different behavior, only
history.

Anno
 
H

hymie!

In our last episode, the evil Dr. Lacto had captured our hero,
(e-mail address removed), who said:
I'd put single quotes aroung the < and >, since they don't need
double quote features.

Just the opposite: I'd put > and $cfile into a single pair of double-quotes:

# opens for read-only by default
open INPUT,$ofile or die "Can't open $ofile: $!";
open OUTPUT,">$cfile" or die"Can't open $cfile: $!";

hymie! http://www.smart.net/~hymowitz (e-mail address removed)
===============================================================================
 
A

A. Sinan Unur

(e-mail address removed) (hymie!) wrote in
In our last episode, the evil Dr. Lacto had captured our hero,
(e-mail address removed), who said:

Just the opposite: I'd put > and $cfile into a single pair of
double-quotes:

# opens for read-only by default
open INPUT,$ofile or die "Can't open $ofile: $!";
open OUTPUT,">$cfile" or die"Can't open $cfile: $!";

From perldoc perlopentut:

In this case, the filename to open is the actual string in $datafile, so
you don't have to worry about $datafile containing characters that might
influence the open mode, or whitespace at the beginning of the filename
that would be absorbed in the 2-argument version. Also, any reduction of
unnecessary string interpolation is a good thing.

Hence, doing as Sam Holden suggested and using

open OUTPUT,'>', $cfile or die "Can't open $cfile: $!";

would be preferable.
 
S

Sam Holden

Perl treats interpolation of arrays differently than interpolation of
scalars. Array interpolation was introduced rather late in the game.
To make the transition as smooth as possible, Perl treats "@" in a string
as a normal character whenever possible. The rather complex handling of
"$" was already in place at the time and was, of course, not changed.

So there really is no good reason for the different behavior, only
history.

I guess that makes sense, after all there was probably at least one
perl script that used @ at the end of a string, but not in the middle
of a string... Maybe... :)

But "history" is as good an answer as any (and a very common one at that).
 
M

Matt Garrish

Anno Siegel said:
So is @" (though Perl doesn't use it), that's not the point.

Perl treats interpolation of arrays differently than interpolation of
scalars. Array interpolation was introduced rather late in the game.
To make the transition as smooth as possible, Perl treats "@" in a string
as a normal character whenever possible. The rather complex handling of
"$" was already in place at the time and was, of course, not changed.

So there really is no good reason for the different behavior, only
history.

I stand corrected. I was under the (false) impression that Perl wouldn't try
and distinguish $" at the end of the string because it could just be that
you were trying to use $". Live and learn...

Matt
 

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,999
Messages
2,570,243
Members
46,836
Latest member
login dogas

Latest Threads

Top