% ------------------------------------------- % latex generated by: booktolatex.cgi % from source file : ../htdocs/books/perl/perl-book.txt % on: 19 April 2024, 10:08am % querystring: books/perl/perl-book.txt % document-root: /var/www/html % script-name: /cgi-bin/booktolatex.cgi % Server-name: bumble.sourceforge.net % Sed-script: booktolatex.sed % ------------------------------------------- \documentclass[a4paper,12pt]{article} \usepackage[margin=0.4cm,noheadfoot]{geometry} \usepackage{color} %% to use colours, use "xcolor" for more \usepackage{multicol} %% for multiple columns \usepackage{keystroke} %% for keyboard key images \usepackage[toc]{multitoc} %% for multi column table of contents \usepackage{tocloft} %% to customize the table of contents \setcounter{tocdepth}{2} %% only display 2 levels in the contents \setlength{\cftbeforesecskip}{0cm} %% make the toc more compact \usepackage{listings} %% for nice code listings %\lstset{language={}, \lstset{language=, %% define special comment delimiters '##(' and ')' moredelim=[s][\color{grey}\itshape\footnotesize\ttfamily]{~(}{)}, basicstyle=\ttfamily, %% fixed pitch font xleftmargin=1cm, %% margin on the left outside the frames breaklines=true, %% break long code lines breakatwhitespace=false, %% break long code lines anywhere breakindent=10pt, %% reduce the indent from 20pt to 10 postbreak=\mbox{{\color{blue}\small$\Rightarrow$\space}}, %% mark with arrow showstringspaces=false, %% dont show spaces within strings framerule=5pt, %% thickness of the frames rulecolor=\color{lightgrey}, frame=l} %% source code settings \usepackage{graphicx} %% to include images \usepackage{fancybox} %% boxes with rounded corners \usepackage{wrapfig} %% flow text around tables, images \usepackage{tabularx} %% change width of tables \usepackage[table]{xcolor} %% alternate row colour tables \usepackage{booktabs} %% for heavier rules in tables \usepackage[small,compact]{titlesec} %% sections more compact, less space \usepackage{enumitem} %% more compact and better lists \setlist{noitemsep} %% reduce list item spacing \usepackage{hyperref} %% make urls into hyperlinks \hypersetup{ %% add "pdftex," if only pdf output is required colorlinks=true, %% set up the colours for the hyperlinks linkcolor=black, %% internal document links black urlcolor=black, %% url links black filecolor=red, citecolor=red, bookmarks=true, pdfpagemode=UseOutlines} % define some colours to use \definecolor{lightgrey}{gray}{0.70} \definecolor{grey}{gray}{0.30} \titleformat{\section}[frame] %% titlesec: create framed section headings {\normalfont} {\filleft \footnotesize \enspace Section \thesection\enspace\enspace} {3pt} {\bfseries\itshape\filright} \title{The Perl Programming Language} \author{} \date{27 October 2011, 6:33pm} \setlength{\parindent}{0pt} % \setlength{\parskip}{1ex} % label lists with stars \renewcommand{\labelitemi}{$\star$} \begin{document} \centerline{\Large \bf The Perl Programming Language} \medskip \begin{center} {\huge ``}\textit{}{\huge ''} \textsc{} \end{center} % ----------------------------------- % the toc should be 2 columns because of the \multitoc package \tableofcontents . The book is set out as a series of ``recipes'' in the style of a ``cookbook'' The perl language and its many modules is a large topic and this document has only been just begun. \section{Perl} [+] Perl is a language which was originally inspired by the Bash shell syntax, as well as by the idea of writing terse but powerful programs. The name perl is not an acronym, since the creator, Larry Wall said he was looking for any name with ``positive connotations''. Perl initially rose to fame through it suitability for writing web-server cgi scripts, since perl, like the unix shells, uses plain text as a kind of ``data interchange format''. [+] The weaknesses of perl: it moves away from the Unix idea of using small programs to do one thing and linking them together with FIFO pipes or streams; it has no built in windowing commands; Its ease of use may encourage bad programming or attract bad programmers. This section will concentrate on one line perl programs and integrating those programs with the bash shell. \section{Learning Perl} \begin{description}[labelindent=1cm, leftmargin=2cm, style=nextline] \item[\url{http://www.perlmonks.org/}] \item[\url{http://learn.perl.org/}] \end{description} \emph{ Display the introduction to the perl documentation } \begin{lstlisting} man perl \end{lstlisting} \begin{lstlisting} perldoc perl ~(the same) \end{lstlisting} \emph{ Set variables f=``bi'' and g=``sm a'' using eval and a perl one liner. } \begin{lstlisting} eval $(perl -e 'print "f=bi;";print "g=\"sm a\"\n"') \end{lstlisting} (this demonstrates ``exporting'' variables from perl to the parent shell) \emph{ Check syntax of a perl one line program but dont run it } \begin{lstlisting} perl -wc -e 'print "\n\n"' \end{lstlisting} \section{Gotchas} \emph{ In a one-line script, print must use ``\textbackslash n'' otherwise no output may appear } \begin{lstlisting} perl -e 'if ( -d ".") { print "folder"; }' ~(doesnt seem to print 'folder') \end{lstlisting} \begin{lstlisting} perl -e 'if ( -d ".") { print "folder\n"; }' ~(correct: prints 'folder') \end{lstlisting} \emph{ Most one line perl scripts should be enclosed in single quotes } \begin{lstlisting} perl -e 'if (!$s) { print "s has no value\n" }' \end{lstlisting} (if double quotes were used, the shell would interpret ``!\$'' first) \emph{ Lines read from standard input have a newline, so you must use '-l' or 'chomp' } \begin{lstlisting} ls | perl -ne 'if (-T "$_") {print "$_ text"}' ~(doesnt work since $_ has \n) \end{lstlisting} \begin{lstlisting} ls | perl -lne 'if (-T "$_") {print "$_ text"}' | less ~(this works) \end{lstlisting} \begin{lstlisting} ls | perl -ne 'chomp; if (-T "$_") {print "$_ text\n"}' | less ~(this works) \end{lstlisting} \section{Perl Documentation} Documentation for the perl language is installed along with the language \emph{ View the start page for the perl documentation } \begin{lstlisting} man perl \end{lstlisting} \begin{lstlisting} perldoc perl ~(the same, more useful on ms windows) \end{lstlisting} \arrayrulecolor{gray} \begin{center} \begin{tabular}{ |rl| } \multicolumn{2}{c}{\textbf{ some perl documentation pages }} \\ \hline \texttt{ man perl } & The start page, contains references to lots and lots of docs \\ \texttt{ man perlintro } & An introduction \\ \texttt{ man perltoc } & A table of contents of perl documentation \\ \hline \end{tabular} \end{center} \emph{ Query the perl ``frequently asked questions'' documents for a word or phrase } \begin{lstlisting} perldoc -q eval \end{lstlisting} \emph{ Save the entire ``perlfunc'' man page in the file ``file.txt'' } \begin{lstlisting} perldoc -T perlfunc > file.txt \end{lstlisting} \emph{ Query the perl faqs for the word 'file' } \begin{lstlisting} perldoc -q ' file' ~(' file' seems to work better than 'file') \end{lstlisting} \emph{ Show the documentation for the CGI module } \begin{lstlisting} perldoc CGI ~(these names are case-sensitive, "perldoc cgi" doesnt work) \end{lstlisting} \begin{lstlisting} man CGI \end{lstlisting} \subsection{Pod The Perl Documentation Format} debian: perl-doc - to use the perldoc tool The perl documentation format is known as the ``pod'' format and is accompanied by a variety of tools to transform it to other documentation formats. The ``perldoc'' tool can be used to query the perl documentation or the documentation for a module \section{Perl Modules} Modules are libraries of code which carry out specific task and save the programmer large amounts of time. One of the strenghts of perl is the very large number of open-source modules available. \arrayrulecolor{gray} \begin{center} \begin{tabular}{ |rl| } \multicolumn{2}{c}{\textbf{ perl modules documentation }} \\ \hline \texttt{ man perlmod } & How modules work \\ \texttt{ man perlmodlib } & How to write and use a perl module \\ \texttt{ man perlmodinstall } & How to install from CPAN \\ \hline \end{tabular} \end{center} \emph{ Show all programs which have perl in the short description } \begin{lstlisting} apt-cache search 'perl' | grep perl | sort | less \end{lstlisting} \emph{ Use a module } \begin{lstlisting} perl -Mmodule -e "print 'hello'" \end{lstlisting} \emph{ Use the CGI module with the ``qw(:standard)'' option } \begin{lstlisting} perl -MCGI=:standard -e "print header, h1('hello')" \end{lstlisting} \emph{ The cpan program can be used to find and install perl modules } \begin{lstlisting} cpan \end{lstlisting} \emph{ Some perl modules may be installed via debian packages or via cpan } \begin{lstlisting} sudo apt-get install libgd-barcode-perl \end{lstlisting} \emph{ Check if the LWP module is installed } \begin{lstlisting} perl -MLWP -e1 \end{lstlisting} \emph{ Print the version number of the LWP module } \begin{lstlisting} perl -MLWP -e 'print $LWP::VERSION' \end{lstlisting} \subsection{Using The Lwp Module} \begin{description}[labelindent=1cm, leftmargin=2cm, style=nextline] \item[\url{http://www.darkspell.com/references/lwpcook.html}] a set of ``recipes'' for using the lwp module \end{description} \emph{ Download a webpage for processing } \begin{lstlisting} perl -e 'use LWP::Simple; $doc = get "http://bumble.sf.net";' \end{lstlisting} \emph{ Download and display a url using the lwp perl module } \begin{lstlisting} PERL -MLWP::Simple -e 'getprint "http://url"' \end{lstlisting} \emph{ Check if a document exists } \begin{lstlisting} use LWP::Simple; if (head($url)) {# ok document exists} \end{lstlisting} \subsection{Using The Cgi Module} \emph{ Send error messages generated by perl to the browser } \begin{lstlisting} use CGI; \end{lstlisting} \begin{lstlisting} use CGI::Carp qw(fatalsToBrowser); \end{lstlisting} \emph{ Print a very simple document with the cgi module } \begin{lstlisting} use CGI; my $cgi = new CGI; print $cgi->header(); print $cgi->start_html(); print "hello cgi"; print $cgi->end_html; \end{lstlisting} \emph{ Indicate the title of the document using the cgi module } \begin{lstlisting} print $cgi->start_html( -title=> "testing cgi") \end{lstlisting} \emph{ Show the file parameter which was sent from an html form } \begin{lstlisting} use CGI; my $cgi = new CGI; print $cgi->header(); print $cgi->start_html(); print "the file parameter is:", $cgi->param('file'); print $cgi->end_html; \end{lstlisting} \emph{ Access the cgi ``environment'' variables from perl } \begin{lstlisting} $sDocumentRoot = $ENV{'DOCUMENT_ROOT'}; \end{lstlisting} \section{Some Useful Modules} \arrayrulecolor{gray} \begin{center} \begin{tabular}{ |rl| } \multicolumn{2}{c}{\textbf{ some useful modules }} \\ \hline \texttt{ HTML::LinkExtor } & Extract links from html \\ \texttt{ File::Find } & Find files \\ \texttt{ Getopt::Long } & Get long and short options for a script \\ \texttt{ Cwd } & Print the current working folder \\ \texttt{ URI::URL } & Extract portions of a url \\ \texttt{ File::Basename } & Get the folder and filename \\ \texttt{ File::Path } & Make folders and delete them (mkpath, rmtree) \\ \texttt{ Benchmark } & Time how long perl code takes to run \\ \texttt{ DataDumper } & Creates a string representation of arrays and hashes \\ \hline \end{tabular} \end{center} \section{Windowing Programs} \begin{lstlisting} use tk; # # \end{lstlisting} \section{Cpan The Online Perl Code Repository} Cpan stands for "comprehensive perl archive network" and is a repository of open-source code modules and libraries which can be used to ease the task of the programmer. ``cpan'' is also an interactive program which allows one to find and download these modules from a command line. The name ``cpan'' was modelled on ``ctan'' which is the the "comprehensive tex archive network" \begin{description}[labelindent=1cm, leftmargin=2cm, style=nextline] \item[\url{http://www.cpan.org/}] the cpan home site \item[\url{http://sial.org/howto/perl/life-with-cpan/}] some information about cpan \end{description} \emph{ Run the ``cpan'' interactive program } \begin{lstlisting} cpan \end{lstlisting} \begin{lstlisting} sudo cpan ~(as a quick fix for permissions problems) \end{lstlisting} \emph{ Show the documentation for the ``cpan'' module } \begin{lstlisting} perldoc CPAN \end{lstlisting} \begin{lstlisting} http://search.cpan.org/perldoc/CPAN ~(the same, in a web-browser) \end{lstlisting} \emph{ ``cpanplus'' is a more modern alternative to cpan } \emph{ Install the latest version of cpan, with passive ftp for firewalls } \begin{lstlisting} perl -MCPAN -e '$ENV{FTP_PASSIVE} = 1; install CPAN' \end{lstlisting} \begin{lstlisting} install CPAN ~(the same, but from within the "cpan" program) \end{lstlisting} \emph{ Search the cpan site for the documentation for the ``LWP::UserAgent'' package } \begin{lstlisting} http://search.cpan.org/perldoc/LWP::UserAgent \end{lstlisting} \subsection{Using The Cpan Program} problems with the ``cpan'' program: \begin{itemize} \item it doesnt tell you how big a module which you are going to install is. \item \end{itemize} \emph{ Run the start up configuration for the cpan program } \begin{lstlisting} cpan o conf init \end{lstlisting} \emph{ Install ``history'' support for cpan (the up arrow obtain the previous command) } \begin{lstlisting} cpan install Term::ReadKey Term::ReadLine ##(didnt work) \end{lstlisting} \emph{ Show the short help for the cpan program } \begin{lstlisting} h | less \end{lstlisting} \emph{ Show details about the module whose name is CGI } \begin{lstlisting} m CGI ~(the exact module name must be written, case sensitive) \end{lstlisting} \emph{ Show all modules which have the text ``CGI'' in their names } \begin{lstlisting} m /CGI/ | less ~(this is a case insensitive search) \end{lstlisting} (problem, hitting 'q' in less exits cpan) \emph{ Show information about the CGI module (using CPAN non-interactively) } \begin{lstlisting} perl -MCPAN -e' CPAN::Shell->m("CGI")' | less \end{lstlisting} \emph{ Show a short description for all modules which have ``CGI'' in the name } \begin{lstlisting} perl -MCPAN -e' CPAN::Shell->m("/cgi/")' | less ~(this is quite slow) \end{lstlisting} (these searches are Not case sensitive) \emph{ Show all available modules on cpan (approximately 70000) } \begin{lstlisting} perl -MCPAN -e' CPAN::Shell->m()' | less ~(this will be VERY slow) \end{lstlisting} (this command took 3 minutes on my ASUS netbook computer) \section{Perl One Line Scripts} \arrayrulecolor{gray} \begin{center} \begin{tabular}{ |rl| } \multicolumn{2}{c}{\textbf{ perl command line switches }} \\ \hline \texttt{ -p } & Loops over each input line and prints it \\ \texttt{ -n } & Loops over each input line but doesnt print it \\ \texttt{ -l } & Remove newline characters when read and restore when writing \\ \texttt{ -e } & Specify a perl expression to use, should be the last switch used \\ \hline \end{tabular} \end{center} \emph{ Print files in the current folder which are text files } \emph{ All the following versions do the same thing } \begin{lstlisting} ls | perl -lne '-T and print' ~(a possible problem with spacey filenames) \end{lstlisting} \begin{lstlisting} ls | perl -lne '-T && print' \end{lstlisting} \begin{lstlisting} ls | perl -lne 'print if -T' \end{lstlisting} \begin{lstlisting} ls | perl -lne '-T "$_" and print' \end{lstlisting} \begin{lstlisting} ls | perl -lne 'if (-T "$_") {print "$_"}' \end{lstlisting} \begin{lstlisting} ls | perl -lne '-T "$_" and print "$_"' \end{lstlisting} \begin{lstlisting} ls | perl -lne '-T $_ and print $_' \end{lstlisting} \begin{lstlisting} ls | perl -lne '(-T "$_") && (print "$_")' \end{lstlisting} \begin{lstlisting} ls | perl -ne 'chomp; if (-T "$_") {print "$_\n"}' \end{lstlisting} The large list of commands above, all of which do the same thing shows the flexibility of the perl syntax. Perl allows certain things to be implied (just like in real language). The most common thing which is implied is ``\$\_'' which can be translated as ``that'' and in a loop is generally the current line or variable. \emph{ Include 2 perl expressions with the -e expression } \begin{lstlisting} perl -e 'print "Hello";' -e 'print " World\n"' \end{lstlisting} \emph{ Print the 2nd field of the input (fields delimited by spaces) } \begin{lstlisting} echo a b c | perl -lane 'print $F[1]' ~(the -n switch loops without printing) \end{lstlisting} \emph{ Print the 1st and 2nd fields of the input lines } \begin{lstlisting} echo a b c | perl -lane 'print "@F[0..1]"' \end{lstlisting} \emph{ Print the first field of a password file (splitting on the ':' f character } \begin{lstlisting} perl -F: -lane 'print $F[0] if !/^#/' /etc/passwd \end{lstlisting} \emph{ Print lines which dont contain the letter 'b' } \begin{lstlisting} (echo a; echo b) | perl -nle 'print if !/b/' \end{lstlisting} \emph{ Print the 3rd line of a file } \begin{lstlisting} perl -nle 'print if $. == 1' file.txt \end{lstlisting} \emph{ Print everyline except the first } \begin{lstlisting} perl -nle 'print unless $. == 1' file.txt \end{lstlisting} \section{Printing To Standard Output} \emph{ Print the results of 2 functions to standard output } \begin{lstlisting} print header(), footer(); \end{lstlisting} \begin{lstlisting} print header, footer; ~(the same) \end{lstlisting} \emph{ Print a string and a function result to standard output } \begin{lstlisting} print "Your name is", name(); \end{lstlisting} \emph{ Print text in single quotes } \begin{lstlisting} perl -e 'print q{#!/usr/bin/perl}' ~(the quotes dont appear?) \end{lstlisting} \section{General Perl Syntax} \section{Loops} \subsection{The Foreach Loop} \emph{ Loop through the elements of an array } \begin{lstlisting} @names = ('Larry', 'John', 'Jack'); foreach (@names) { print $_."\n"; } \end{lstlisting} \emph{ Loop through the elements of a literal list } \begin{lstlisting} foreach (qw/one 2 three 4/) { print $_."\n"; } \end{lstlisting} \subsection{If Statement} \emph{ The if statement has a c-like syntax } \begin{lstlisting} if (test) {... } \end{lstlisting} \subsection{Global Variables} \emph{ Import the variables \$TRUE, \$FALSE etc } \begin{lstlisting} do 'global.pl'; use vars qw($TRUE $FALSE $LANGUAGE); \end{lstlisting} \subsection{Different Types Of Quotes} \arrayrulecolor{gray} \begin{center} \begin{tabular}{ |rl| } \multicolumn{2}{c}{\textbf{ quote characters }} \\ \hline \texttt{ qq } & Be used anywhere " can be used \\ \texttt{ qw } & Quote a list of words, eg; qw/one 2 three/ \\ \hline \end{tabular} \end{center} \subsection{Local Variables} \emph{ Create a local variable } \begin{lstlisting} my $string; \end{lstlisting} \subsection{Array Variables} \emph{ Assign a list of text files in the current folder to the array @list } \begin{lstlisting} @list = grep { -f && -T } glob(’*’) \end{lstlisting} \emph{ Show all text files in the current folder } \begin{lstlisting} perl -e 'print join "\n", grep {-T}<*>' \end{lstlisting} \subsection{String Variables} \emph{ Exit if the "s" variable has no value } \begin{lstlisting} perl -e 'if (!$s) { die "s has no value"; }' \end{lstlisting} \emph{ Join to strings together } \begin{lstlisting} $s = "green"."tree"; ~($s is now 'greentree') \end{lstlisting} \emph{ Append a 'here document' to a string } \begin{lstlisting} $s .= <index.txt") || die "Could not open the file for writing!"; print F "$s"; close F; \end{lstlisting} \subsection{Copying Files} \emph{ Copy a file to another name or exit if it is not possible } \begin{lstlisting} use File::Copy; my $f = "list"; copy($f, "$f.1") || die "could not copy file $f, because: $!"; \end{lstlisting} \subsection{Creating A Temporary File} \emph{ Create a temporary file, without ever knowing its name } \begin{lstlisting} use IO::File; $fh = IO::File->new_tmpfile() or die "Couldnt make the temp file: $!"; \end{lstlisting} \emph{ Another way } \begin{lstlisting} use File::Temp \end{lstlisting} \subsection{File Globbing} 'file globbing' refers to expanding a wildcard character (such as '*' or '?') into a list of valid file names for the local computer. \emph{ Display files with a '.txt' extension in the current folder } \begin{lstlisting} perl -e 'for (glob("*.txt")) { print $_."\n"}' \end{lstlisting} \begin{lstlisting} perl -e 'foreach (glob("*.txt")) { print $_."\n"}' ~(the same) \end{lstlisting} \begin{lstlisting} perl -e 'foreach $f (glob("*.txt")) { print $f."\n"}' ~(the same again) \end{lstlisting} \section{Using Folders Or Directories} \emph{ Print the directory part of a file name } \begin{lstlisting} use File::Basename; print dirname("/home/username/index.txt"); \end{lstlisting} \section{Perl Standard Functions} * \begin{lstlisting} perldoc perlfunc \end{lstlisting} \subsection{Writing Perl Functions} \emph{ Append the result of a function to a scalar variable } \begin{lstlisting} $sOutput .= listData($configFile, $siteRoot, ''); \end{lstlisting} \subsection{Importing Other Files} \emph{ Import the file ``move.pl'' which contains a function and is in the ``lib'' folder } \begin{lstlisting} require 'lib/move.pl'; \end{lstlisting} \section{Text Files} \emph{ Change aaa for bbb and print each line } \begin{lstlisting} perl -p -e 's/aaa/bbb/' test.txt ~(the file is not changed) \end{lstlisting} \emph{ Change aaa for bbb and print each line } \begin{lstlisting} perl -pi -e 's/aaa/bbb/' test.txt ~(the file IS changed) \end{lstlisting} \emph{ Replace the word big with small in .txt files and backup to .bak } \begin{lstlisting} perl -p -i.bak -e 's/\bbig\b/small/g' *.txt \end{lstlisting} \emph{ Recursive replacement of text in this and subdirectories } \begin{lstlisting} perl -p -i.bak -e 's/\bbig\b/small/g' $(find ./ -name "*.txt") \end{lstlisting} \begin{lstlisting} perl -p -i.bak -e 's/\bbig\b/small/g' $(grep -ril text *) \end{lstlisting} \emph{ Insert one line in a text file } \begin{lstlisting} use Tie::File \end{lstlisting} \end{document}