Common mistakes made with CGI scripting include:

	1. If you intend to run the script on a Sun Microsystems operating
	   system such as Solaris, it must be in that systems ASCII format.
	   Therefore, if you create the file on a DOS based OS, you must
	   run the command: dos2unix once the file is uploaded to the
	   Solaris machine. This ASCII conversion is not necessary for a
	   machine running Linux.

	2. You must change the script file's access permissions to public
	   to allow public access to the file via HTTP. This is done with
	   the chmod command. example: $chmod 755 myscript.pl
	   7 = read, write, and execute permissions for 'owner'.
	   5 = read, execute permissions for 'group'.
	   5 = read, execute permissions for 'public'.

	3. Remember that when the CGI script is executed via HTTP, the
	   script is run with server rights. For example: when you try
	   to execute commands on UNIX machines, if you (the user) don't
	   have permissions set for the scripts or executables, you will
	   not be allowed to run the command. Server permissions are set
	   by the administrator and may not be able to create files or
	   modify files if the server does not have permission. Keep this
	   in mind if you want to use LOCK files for scripts.


The "use strict;" line will enforce some very handy error checking.
It will make sure you don't use a variable that is not declared.
You must predeclare a variable. And, you either have to fully qualify
a variable (such as $packagename::varname), import it the variable
(such as happens with use or 'import'), or specifically tell the processor
that you want this variable to be used as global (such as:
use vars ('%formdata'));

To find perl on a new or unfamiliar machine:
	% which perl
#!/usr/bin/perl
	use perl as the interpreter
#!/usr/bin/perl -w
	use perl with warnings


eval "print \"Hello World\n\"";
while(<>) {
	eval;
}
special vars:
	$_ - scalar var
	@_ - array var
	%_ - hash var
	$@ - evals error box
	$! - dies return value
	$/ - holds input record seperator (new line)
#----------------------------------------------------------------------------------

LISTS

split /PATTERN/, EXPR, LIMIT
	if EXPR is not present, split evals $_
	if PATTERN is not present, split works on whitespace
	% print split /,/, "H,e,l,l,o";			#-> hello

sort SUBNAME LIST
sort BLOCK LIST
sort LIST
	% print sort ("c","b","a");			#-> abc
	% print sort {$a cmp $b} ("c","b","a");		#-> abc
	% print sort {$b cmp $a} ("c","b","a");		#-> cba
	% print sort {$a <=> $b} (3,2,1);		#-> 123

reverse LIST
	% print reverse(1,2,3);				#-> 321

grep BLOCK LIST
grep EXPR LIST
	% print grep(!/x/, a,b,x,d);			#-> abd

scalar EXPR
	to force a LIST to a scalar variable in case a function
	return is unpredictable:
	% print scalar(1,2,3);				#-> 3

#----------------------------------------------------------------------------------
range operator:
	for(1 .. 5) {print "Hello\n";}

#----------------------------------------------------------------------------------

http://www.civeng.carleton.ca/Courses/Grad/1995-96/82.562/software/index.html#perl
http://www.antipope.org/charlie/index.html
http://www.antipope.org/charlie/nonfiction/tkperl/ptk-4.html#Sharp_operators
-----------------------------------------------------------------
$jabberwocky =~ /toves(\s)did/is;
The =~ operator returns true if we've found the pattern in the variable $jabberwocky; it returns false if the pattern isn't there. 
But if the pattern is found, it also sets some special variables: 
$& contains the entire matched string 
$` contains everything in the string before the match 
$' contains everything in the string after the match 
-----------------------------------------------------------------
To change the target string, we use the substitute (s///) expression rather than the simple match // expression. It looks like this: 
$scalar_to_change =~ s/search_for_this/replace_with_that/;
-----------------------------------------------------------------
/g = global (all not just words)
$my_target = "She smiled at him. 'I travelled two miles today', she said.";
$my_target =~ s/miles/kilometres/g;
print $my_target;	# She skilometresd at him. 'I travelled two kilometres today', she said.
-----------------------------------------------------------------
$this =~ s/replacewith/this/is;		# /is at end?
$this =~ s/.+?(the.+\Z)/$1/is;		# The +? means minimum amt of string.
-----------------------------------------------------------------
/e
$a =~ s/something/myfunc($&)/ge;
$my_target = "She smiled at him. 'I travelled 2 miles today', she said.";
$my_target =~ s/
	(.+\W)		# look for some text
	(.+?)		# followed by just one word
	(\Wmiles)	# then "miles"
	(\W.+)		# then some more words
	/print $1, ($2 * 1.61), " kilometres ", $4, "\n";
	/ex;
print $my_target;
-----------------------------------------------------------------
@words = split(/\W/, $line);			# returns array.
$words    = split(/\W/, "This is a sentence");	# returns 4.
$line = join(" ", @words);			# joins array @words but will not be the same as the above split b/c "/W".

while (<>) {					# split scalar $_. <> = the standard input.
	$words += split(/\W/); # split words in $_
}
	print "stdin contained $words words\n";
-----------------------------------------------------------------
@found = grep(/pattern/, (<>));
	# scans the standard input (which is grouped in brackets, thus indicating that it is to be treated as an array) for /pattern/. Every line on the standard input is scanned in turn, and every time the pattern match evaluates to TRUE the result is added to the output array @found.
-----------------------------------------------------------------
local ($f) = shift @_;	# shift() takes the first element from a list and returns it, shortening the list by one. It's comminly used for getting at the first item in a parameter list passed to a subroutine.
sub my_complex_sub($;@)	# means that my_complex_sub expects a scalar argument, and an optional list.
-----------------------------------------------------------------
%my_hash = (
	"color" => "red",
	"music" => "ambient",
	"taste" => "chocolate"
	) ;  # define %my_hash;
%your_hash = (
	"program" => "test5.pl",
	"language" => "perl",
	"beast" => "camel"
	); # define a second hash
sub print_hashes {
	local ($hashes_to_print) = shift @_;
	local (%tmp_hash);
	foreach $num (1 .. $hashes_to_print) {
		*tmp_hash = shift @_;
		print "Printing hash $num\n";
		foreach $key (keys %tmp_hash) {
			print "$key => ", $tmp_hash{$key}, "\n";
		}
	}
}
print_hashes(2, *my_hash, *your_hash);
-----------------------------------------------------------------
You can take a reference to a variable by prefixing it with a backslash. For example: 
$my_ref = \%some_hash;	# Stores a reference to %some_hash in the scalar $my_ref. While: 
	print $$hashref{quark}, "\n";
$my_array = \@list	# Stores a reference to the array @list in $my_array. 
You can also store references to scalars: 
$my_scalar_ref = \$scalar
-----------------------------------------------------------------
@array1 = qw( red blue green );
@array2 = qw( yellow purple violet );
@array3 = qw( mauve pink gold );
@two_d_array = ( \@array1, \@array2, \@array3);
print ${ @two_d_array[1] }[1], "\n";	# prints purple.
---------
my (@insects) = qw(ant bee moth wasp);
my (@stings) = qw(mild painful non-existent vicious);
describe(\@insects, \@stings);
sub describe {
	my ($creepie) = shift @_;
	my ($bite)    = shift @_;
	for ($i = 0; $i < 4; $i++) {
		print "A ", $$creepie[$i], " has a ", $$bite[$i], " sting\n";
	}
}
PRINTS:
	A ant has a mild sting
	A bee has a painful sting
	A moth has a non-existent sting
	A wasp has a vicious sting
The important thing to note here is that the arrays @insects and @stings have been kept separate while being passed through to describe(). If we had passed the arrays through, rather than references to them, they'd have been munged together in @_.