There are several command line options that every Perl programmer should know.\n\n!!General\n* {{{-c}}} compile only, don't run\n* {{{-w}}} run with warnings turned on\n* {{{-d}}} run under the debugger\n* {{{-i}}} modify target files //in-place//\n{{{\n perl -i.bak my_script.pl *.html\n}}}\n* {{{-T}}} run script in [[Taint mode]]\n!!One-liners\n* {{{-e}}} supply a Perl expression, instead of a script\n* {{{-M}}} load a module\n{{{\n perl -MLWP::Simple=get -e'get( $ARGV[0] );' http://www.google.com\n}}}\n* {{{-n}}} wrap the script in a {{{while(<>){ } }}}loop\n* {{{-p}}} wrap the script in a {{{while(<>){ } continue { print; } }}}loop\n{{{\n perl -i.bak -p -e"s/old\s.host\s.name/new.host.name/g;" *.html\n}}}\n\n[[Command Line tricks]]
{{{\n perl -de0\n}}}\n\non the command line gives you an interactive Perl environment.\n
Sometimes you want to execute a piece of code based on a supplied string.\nThe obvious example of this would be some form of interpreter.\nYou can code a long {{{if}}}-{{{elsif}}} chain, or you could use a command table.\n{{{\nmy %Commands = (\n print => sub { print @_; },\n add => sub { my ($a, $b) = @_; print $a + $b, "\sn"; },\n quit => sub { exit( 0 ); },\n);\n\nsub run_command\n{\n my $line = shift;\n my ($cmd, @args) = split( " ", $line );\n if(exists $Commands{$cmd})\n {\n $Commands{$cmd}->( @args );\n }\n else\n {\n print "Command '$cmd' not recognized.\sn";\n } \n}\n}}}\n\nIt is not very efficient for 3 commands, but it scales nicely up to dozens or hundreds.
Perl supports a few conditional statements:\n\n* {{{if}}} - execute block if condition is true\n* {{{elsif}}} - execute block if condition is true\n* {{{unless}}} - execute block if condition is false\n\n{{{\nunless(is_weekend( $day ))\n{\n if($hours < 6)\n { \n too_early( $hours );\n }\n elsif($hours > 18)\n {\n after_work( $hours );\n }\n else\n {\n at_work( $hours );\n }\n}\n}}}\n\n[[Definition of truth]]
Context is one of the pieces of magic that allows Perl to usually do what you want without extraneous syntax. Perl can often //infer// how you want an expression to behave based on the context in which it exists. Perl supports the following contexts:\n\n* list context\n* scalar context\n** numeric context\n** string context\n** boolean context\n* void context\n\nThis magic is what allows an array to return a list of its contents where a list is expected, but return the number of items it contains in scalar context. For example,\n{{{\nif(@array > 5)\n{\n foreach my $item (@array)\n {\n # process item\n }\n}\n}}}\n\nHow do you determine context?: [[wantarray]]\nHow do you set context?: [[Setting context]]\n[[Context gotchas]]
The main //gotcha// relating to contexts is the fact that the arguments to a subroutine are //always// in list context.\n\n{{{\nsub trace\n{\n my $msg = shift;\n print "$msg\sn";\n}\n\ntrace( localtime );\n}}}\n\nSome people might expect this to print the time and date as a string because that is what {{{localtime}}} returns in scalar context, and we are expecting to only use on value.\n\nUnfortunately, the subroutine call provide list context, resulting in only printing the seconds.
How do you debug in Perl?\n\n* print statements\n** crude, but effective\n** prints exactly what you want\n** requires nothing but Perl itself\n* the perl debugger\n** {{{perl -d script}}}\n** a line-based debugger\n** supports breakpoints, single-stepping, expression evaluation, etc.\n** not the friendliest interface in the world\n** part of the perl interpreter\n* ~PerlTkDb\n** Module: Devel::ptkdb\n** {{{perl -d:ptkdb}}\n** ~GUI-based debugger interface\n** Available on CPAN\n** http://world.std.com/~aep/ptkdb/\n\nSome ~IDEs support debugging in Perl.
[[How to Use This Document]]\n[[Overview]]\n
Perl has an odd, but useful, definition of truth.\n\n> ''Anything that is not false, is true.''\n\nSo, you may wonder what is false. In Perl, the following values are false:\n\n* {{{undef}}} - the undefined value\n* {{{0}}} - zero\n* {{{"0"}}} - a string containing only a zero\n* {{{0.0}}} - a floating-point zero\n* {{{""}}} - an empty string\n* {{{()}}} - and empty list\n\nEverything else is true, including:\n\n* {{{"false"}}} - the string 'false'\n* {{{"0, but true"}}} - when used as a number, it's {{{0}}}\n* {{{( undef )}}} - the list is not empty\n
\n* {{{<FH>}}} returns a line from the file handle {{{FH}}}\n* {{{<DATA>}}} returns a line from the script after the {{{__DATA__}}} or {{{__END__}}}\n* {{{<$fh>}}} returns a line from the filehandle stored in {{{$fh}}}\n* {{{<>}}} returns a line from the magic {{{ARGV}}} filehandle\n
A hash is like an array, except that it is indexed by strings, not integers.\n\nOften used for mapping a string to something else.\n{{{\nmy %short_months = (\n 'January' => 'Jan',\n 'February' => 'Feb',\n 'March' => 'Mar',\n 'April' => 'Apr',\n 'May' => 'May',\n 'June' => 'Jun',\n 'July' => 'Jul',\n 'August' => 'Aug',\n 'September' => 'Sep',\n 'October' => 'Oct',\n 'November' => 'Nov',\n 'December' => 'Dec',\n);\n\nprint "$short_month{December}\sn";\n}}}\n* [[Hash tips]]\n* [[Hash tricks]]
* Hashes are always indexed by a string, even if the string looks like a number.\n* Use the //fat comma// ({{{=>}}}) when building hashes.\n* Leave a trailing comma on the last item when building a hash with a list.\n* Use {{{exists}}} to test if an entry in a hash exists.\n* Use {{{delete}}} to remove something from a hash.\n\n\n
Hashes are an extremely powerful feature in Perl. Using them wisely can really simplify your code.\n\nHashes convert to and from lists easily, which allows some interesting tricks.\n\n{{{\nmy %short_month_to_long_month = reverse %short_month;\n}}}\n\nThe {{{map}}} operator can often be used to create hashes that are used as lookup tables or caches.\n\n{{{\nmy $monthnum = 0;\nmy %month_number_from_name = map { $_ => ++$monthnum } keys %short_month;\n}}}\n
This is a quick note on how to find things in this document.\n\nThe list to the left in the lighter blue cover the main topics to be covered in the two sessions.\nThe darker blue links at the bottom are tags that provide access to subsets of the information.\n\n* basics - are things that we all should know\n* tips - cover information that you probably should know, but may have forgotten\n* tricks - cover information that you may not use every day, but are still important for you bag of tricks\n* gotchas - are places where you and Perl may disagree on how things work\n* apr - are the topics we covered at the April meeting\n* may - are the topics we covered at the May meeting\n\nFeel free to explore, no one path through this document is best.
* Most input loops start with {{{chomp}}} to remove the newline.\n* Many input loops have an explicit test to ignore empty lines to avoid wasting processing time.\n* Some input loops have a test for //comment lines// that we don't want to process.\n\nAn example containing all of these would look like this:\n{{{\nLINE:\nwhile(<>)\n{\n chomp;\n s/#.*//; # remove trailing comments.\n next LINE if /^\ss*$/; #skip blank lines\n\n # begin actual processing.\n}\n}}}\n
{{{\nwhile(<>)\n{\n}\n}}}\n\nThis construct reads lines one at a time from either standard input or the files listed on the command line into the variable {{{$_}}}. The loop ends when there are no more lines to read. Which leads us to the [[Diamond Operator]].\n\n[[Input Loop tips]]
When a variable is used in a double quote string, its value is //interpolated// or converted into string form and inserted into the value of the string.\n\n!! Scalar interpolation\nA scalar value is interpolated by conversion to a string. Most of these is obvious, but there are a few that are different.\n\n* {{{undef}}} - interpolates as an empty string. Gives a warning if {{{use warnings;}}} is on.\n* references - interpolate into a name and internal hex address. This is not particularly useful for most applications.\n\n!! List interpolation\nList interpolation is not used as often as scalar interpolation.\n\nA list is interpolated by interpolating each item in the list and joining them by the value of the {{{$"}}} variable. This variable defaults to a single space.\n\n!! Hash interpolation\nThere is no such thing as hash interpolation.\n\n[[Interpolation tips]]\n[[Interpolation tricks]]
Interpolation of variables and escape sequences into double-quoted strings makes formatting output in Perl very easy.\n\nIf you don't want to interpolate a variable into a string, there are several ways to prevent it:\n* Use a single quoted string: {{{'$fred is the name of the variable'}}}.\n* Escape the sigil: {{{"\s$fred is the name of the variable'}}}.\n* Build the string in pieces: {{{ "$" . "fred is the name of the variable"}}}.
Sooner or later you want to interpolate an expression into a string.\nThere is no built-in way to do this.\nHowever, there is a nasty trick that allows you to do it.\n\n{{{\n print "The sum of 17 and 42 is @{[ 17 + 42 ]}\sn";\n}}}\n\nDereference an anonymous hash containing the single value generated by your expression.\n\nI told you it was nasty.
A //list// contains zero or more scalar values. An //array// is a variable that holds a list.\n\n* {{{@array}}} - refers to the whole array\n* {{{$array[0]}}} - refers to the first element of the array\n* {{{@array[0,1]}}} - returns a list of the first two elements of the array\n* {{{$#array}}} - the index of the last element\n* {{{scalar @array}}} - the number of elements in the array\n\n* [[List tips]]\n* [[List tricks]]
Perl doesn't really have a //struct// or //record// data type. People often use hashes instead. When you need more than one of these structures, you get a list of hashes.\n{{{\nmy @machines = (\n { name => 'enterprise', ip => '10.0.0.2', purpose => 'file server' },\n { name => 'defiant', ip => '10.0.0.1', purpose => 'router/firewall' },\n { name => 'reliant', ip => '10.0.0.3', purpose => 'email server' },\n { name => 'voyager' ip => '10.0.0.4', purpose => 'vpn gateway' },\n);\n}}}
Technically, this is a //list of array references//. But, that sounds much more awkward than //lists of lists//.\n{{{\nmy @magic_square = (\n [ 16, 3, 2, 13 ],\n [ 5, 10, 11, 8 ],\n [ 9, 6, 7, 12 ],\n [ 4, 15, 14, 1 ],\n);\n}}}\n\nIf the lists are all the same length, we have a 2D matrix. Obviously, the scalars in the inner lists are not required to be numbers they may be any scalar.
* Perl lists can contain any form of scalar data.\n* A list is not required to have the same kind of data in each element of the list.\n* In scalar context, a list returns the number of items in the list.\n* Perl provides several tools for manipulating lists.\n** {{{foreach}}}\n** {{{push}}} and {{{pop}}}\n** {{{shift}}} and {{{unshift}}}\n** {{{split}}} and {{{join}}}\n** {{{map}}}, {{{grep}}}, and {{{sort}}}\n\nList literals are created using parenthesis {{{ () }}}.\n\nSee the CPAN module {{{List::Util}}} for even more tools.
* If you need a //stack// or //lifo//, use an array with the {{{push}}} and {{{pop}}} operators.\n* If you need a //queue// or //fifo//, use an array with the {{{push}}} and {{{shift}}} operators.\n* Use the {{{qw//}}} operation to create a list from a group of words.\n{{{\nmy @month_names =\n qw/January February March April May June July\n August September October November December/;\n}}}\n* Use the range operator {{{..}}} to build a list of numbers.\n{{{\nmy @indices = ( 1..12 );\n}}}\n\n[[Uniquing a List]]
Perl has the loop statements you expect and maybe a couple more.\n\n* {{{for}}} - two forms\n* {{{foreach}}} - an alias for {{{for}}}\n* {{{while}}} - loop while expression is true\n* {{{until}}} - loop while expression is false
[[Overview]]\n[[Rules]]\n[[Comand Line]]\n[[Variables]]\n[[Input While Loop]]\n[[Diamond Operator]]\n[[Regexes]]\n[[Modifiers]]\n[[Subroutines]]\n[[Context]]\n[[Resources]]\n<<tag basics>>\n<<tag tips>>\n<<tag tricks>>\n<<tag gotchas>>\n<<tag apr>>\n<<tag may>>
{{{\n doit() if $time == $that_time;\n print "foo has changed\sn" unless $quiet;\n doit( $_ ) foreach 1..10;\n}}}\n\nModify a statement with a trailing conditional or loop. Which are available?\n* <<slider condSlider [[Conditional statements]] conditionals "Overview of conditionals.">>\n* <<slider loopSlider [[Loop statements]] looping "Overview of looping constructs.">>\n\nThe expressions used as conditionals are executed in boolean [[Context]].\n\n[[Statement modifier tips]]\n
* Try to make expressions easier to read.\n* Don't try to do it all at once.\n* Recognize when you need to break an expression up.\n* Use {{{m//}}} when you know what to keep.\n* Use {{{split}}} when you know what to discard.
* Perl numbers can be either integers or floating point numbers.\n* Integer literals are specified in one of several bases, including\n** {{{123}}} - decimal\n** {{{0123}}} - octal\n** {{{0x123}}} - hexadecimal\n** {{{0b1101}}} -binary\n* Floating point numbers can be specified in the obvious formats:\n** {{{3.1415}}}\n** {{{6.6260755e-34}}}\n\n[[Number tips]]
* Perl handles extremely large or small numbers by changing internal representation as needed.\n* Large numbers are sometimes hard to read as literals. Perl allows the use of an underscore to group numbers.\n{{{\nmy $light_year_m = 9_460_730_472_580_800;\n}}}\n* The {{{oct}}} operator converts strings to numbers using the appropriate base indicator.\n** //Warning//: numbers with no indicator are treated as octal, not decimal.
!!What every Perl programmer should know.\n\nLet's start with the basics.\n\n* Perl is a dynamic language\n** No compile, link, run cycle\n** dynamically typed.\n* Contrary to what you may have heard, Perl is not interpreted\n** Compiled to an internal format (similar to bytecodes) and run in memory\n* Creator is Larry Wall
References allow Perl to support more advanced data structures and object oriented programming.\n\n* References are created using the backslash operator {{{ \s }}}\n** Scalar reference: {{{\s$name}}}\n** Array reference: {{{\s@names}}} or {{{ [ 'fred', 'barney', 'wilma', 'betty' ] }}}\n** Hash reference: {{{\s%last_names}}} or {{{ { fred => 'flintstone', barney => 'rubble' } }}}\n\nA reference is a scalar, so it may be stored in an array or hash. This allows the creation of multidimensional arrays and nested data structures.\n\n[[Reference tips]]\n[[Reference tricks]]
References allow you to create nested data structures\n\n* <<slider chkLOL [[List of Lists]] "List of lists">>\n* <<slider chkLOH [[List of Hashes]] "List of hashes">>\n* <<slider chkCmdTbl [[Command Table]] "Command table">>\n\nWhen working with nested data structures, the {{{Data::Dumper}}} Perl module is your friend.
There are many different ways to dereference a reference. I prefer to pick a simple approach:\n\n* If I need the whole referenced item, I use the //sigil and curly brace// approach.\n{{{\n foreach(@{$array_ref})\n {\n # do something\n }\n}}}\n\n* Otherwise, I use the //arrow// syntax.\n{{{\n $array_ref->[0] = 5;\n $hash_ref->{fred} = 'flintstone';\n $code_ref->( 17, 42 );\n}}}
Perl has an extremely comprehensive system of regular expressions. A regular expression is like a little program for performing fuzzy matching on a string.\n{{{\n print "$str is an integer\sn" if $str =~ /^\sd+$/;\n print "$str is a C-style identifier\sn" if $str =~ /^[_a-zA-Z]\sw+$/;\n}}}\nPerl uses regular expressions for matching strings using {{{m//}}} and for doing search and replace on strings using {{{s///}}}.\n\n* [[Regular expression tips]]\n* [[Regular expression tricks]]
Regular expresions are like little programs in a different language. It is worth the effort to try to make them more readable.\n\n* Comment intent before the regular expression.\n* Use {{{x}}} option to break up and comment your expression.\n** ignore whitespace\n** ignore Perl comments\n* Build a regex out of smaller regexes\n\nWhich would you prefer to maintain?\n{{{\n $str =~ /((?:\s(\sd\sd\sd\s) *|\sd\sd\sd-?)?\sd\sd\sd-\sd\sd\sd\sd)/;\n}}}\n{{{\n # US phone number\n $str =~ m{( # capture\n (?:\s(\sd\sd\sd\s)\ss* # area code in parens with optional whitespace\n |\sd\sd\sd-? # bare area code with optional dash\n )? # area code is optional\n \sd\sd\sd-\sd\sd\sd\sd # seven digit number\n )\n }x;\n}}}\n{{{\n # US phone number\n my $bare_area_code = qr/\sd\sd\sd/;\n my $area_code = qr{(?:\s( $bare_area_code \s) \ss*\n | $base_area_code -?\n )\n }x;\n my \n $str =~ m{( $area_code? # area code is optional\n \sd\sd\sd-\sd\sd\sd\sd # seven digit number\n )\n }x;\n}}}\n\nKnow when to use and when not to use regular expressions.\n* [[When to use Regexes]]\n* [[When not to use Regexes]]\n\n[[More Regex tips]]
* Change delimiters on m// and s/// to simplify expressions.\n{{{\n # Which is better\n $file =~ s/^.*\s/([^\s/]*)$/$1/;\n #or\n $file =~ s#^.*/([^/]*)#$1#;\n}}}\n* Using {{{'}}} for delimiters stops variable interpolation.\n* Don't forget matching delimiters {{{()}}}, {{{ {} }}}, {{{[]}}}, etc.\n* Remember non-greedy matching: {{{*?}}}, {{{+?}}}, {{{??}}}
!! Books\n* //Programming Perl, 3rd Edition//, Wall, Christiansen, and Orwant\n* //Perl Cookbook//, Christiansen and Torkington\n* //Mastering Regular Expressions//, Friedl\n* //Learning Perl//, Schwartz\n* //Effective Perl Programming//, Hall and Schwartz\n* //Perl Best Practices//, Conway\n\n!! Websites\n* [[Perl.com|http://www.perl.com/]]\n* [[The Perl Directory|http://www.perl.org/]]\n* [[CPAN|http://www.cpan.org/]]: The Comprehensive Perl Archive Network\n* [[The Perl Monastery|http://perlmonks.org/]]\n* [[The Perl Review|http://www.theperlreview.com/]]: The Perl Review Magazine\n* [[use Perl;|http://use.perl.org/]]: Perl news site\n\n!! Modules\n* [[CPAN|http://www.cpan.org/]]: The Comprehensive Perl Archive Network\n* {{{Data::Dumper}}}\n* {{{List::Util}}}\n* {{{Scalar::Util}}}\n* {{{Test::More}}}\n* {{{Test::Harness}}}\n* {{{Getopts::Std}}}\n* {{{Getopts::Long}}}\n* {{{LWP}}}\n* {{{WWW::Mechanize}}}\n
!! Rule number 1\n{{{\nuse strict;\n}}}\nMake several questionable practices into errors.\n* Using undeclared variables\n* Symbolic references\n* Using barewords\n\n!! Rule number 2\n{{{\nuse warnings;\n}}}\nDisplay a message on other less dangerous questionable practices.\n\nFollowing these rules will make programming in Perl much easier.\n\n[[pragma tips]]
A scalar holds a single piece of data. Examples of scalar data include:\n\n* [[Number]]: {{{123}}}, {{{3.1415}}}\n* [[String]]: {{{"Hello, world!}}}, {{{'Another string'}}}\n* {{{undef}}}\n* [[Reference]]\n* file handle\n* directory handle\n{{{\nmy $num = 17;\n}}}\n* [[Scalar tips]]\n* [[Scalar tricks]]
* A scalar variable can hold //any// sort of scalar data.\n* If you try to use a string as a number, Perl will attempt to convert its value into a number.\n* If you try to use a number as a string, Perl will convert its value into a string.\n* If you try to use a scalar where a boolean is needed, Perl applies the [[Definition of truth]].\n* Printing scalars is easy through [[Interpolation]]
* A variable that has never been assigned has a value of {{{undef}}}.\n* A variable can be assigned to {{{undef}}}.\n* When used as a number, {{{undef}}} becomes {{{0}}}.\n* When used as a string, {{{undef}}} becomes {{{''}}}.\n* Scalars can be incremented with {{{++}}}.\n** For numbers, this works as expected.\n** It also works for strings, with the letters being incremented starting from the right.
The three major kinds of context are set pretty much the way you would expect.\n\n* Scalar context\n** Assignment to a scalar\n** Use in a conditional expression\n** Use in an arithmetic expression\n** Argument to {{{scalar}}}\n* List context\n** Assignment to an array\n** Surrounded with parentheses {{{( )}}}\n** Surrounded by square braces {{{[ ]}}}\n** Arguments to a subroutine.\n* Void context\n** Not assigned to anything or used in an expression
tips, tricks, and common knowledge
What Every Perl Programmer Should Know
It is easy to overuse statement modifiers. Here are some tips to help keep them in line.\n\n* Only use statement modifiers with simple conditions.\n* Only use statement modifiers with simple statements.\n\nOne of the best uses of statement modifiers is for breaking out of a loop.\n\n{{{\nwhile(<>)\n{\n next if /^\ss*$/; # skip blank lines\n next unless /^\ss+\sw+ /; # valid line must start with an identifier\n # process command\n}\n}}}
Perl provides many ways of manipulating and creating strings.\n\n* {{{join}}} and {{{split}}}\n* {{{m//}}}, {{{s///}}}, {{{tr///}}}\n* {{{substr}}}\n* single quoted: {{{'fred'}}}, {{{q/barney/}}}\n* double quoted: {{{"fred"}}}, {{{qq/barney/}}}\n* backticked: {{{`date`}}}, {{{qx/date/}}}\n* //Here docs//:\n{{{\nmy $string = <<EOS;\nThis is a long string.\nMuch longer than your normal string.\nI think that is enough for now.\nEOS\n}}}\n\n[[String tips]]
* Double quoted strings interpolate:\n** scalars\n** lists\n** escape sequences: {{{\sn}}}, {{{\st}}}, etc.\n* If you don't need interpolation, use single quotes {{{ 'fred' }}}.\n* Other places that Perl does double-quote interpolation:\n** Back ticks: {{{`date`}}}\n** match operator: {{{m/fred/ }}}\n** substitution operator: {{{s/fred/bianca/ }}}\n* Here docs interpolate by default, but if you surround the delimiter string with single quotes it does not.
/***\n!Colors Used\n*@@bgcolor(#8cf): #8cf - Background blue@@\n*@@bgcolor(#18f): #18f - Top blue@@\n*@@bgcolor(#04b): #04b - Mid blue@@\n*@@bgcolor(#014):color(#fff): #014 - Bottom blue@@\n*@@bgcolor(#ffc): #ffc - Bright yellow@@\n*@@bgcolor(#fe8): #fe8 - Highlight yellow@@\n*@@bgcolor(#db4): #db4 - Background yellow@@\n*@@bgcolor(#841): #841 - Border yellow@@\n*@@bgcolor(#703):color(#fff): #703 - Title red@@\n*@@bgcolor(#866): #866 - Subtitle grey@@\n!Generic Rules /%==============================================%/\n***/\n/*{{{*/\nbody {\n background: #fff;\n color: #000;\n}\n\na{\n color: #04b;\n}\n\na:hover{\n background: #04b;\n color: #fff;\n}\n\na img{\n border: 0;\n}\n\nh1,h2,h3,h4,h5 {\n color: #703;\n/* background: #8cf; */\n border-bottom: 1px black solid;\n}\n\n.button {\n color: #014;\n border: 1px solid #fff;\n}\n\n.button:hover {\n color: #014;\n background: #fe8;\n border-color: #db4;\n}\n\n.button:active {\n color: #fff;\n background: #db4;\n border: 1px solid #841;\n}\n\n/*}}}*/\n/***\n!Header /%==================================================%/\n***/\n/*{{{*/\n.header {\n background: #04b;\n}\n\n.headerShadow {\n color: #000;\n}\n\n.headerShadow a {\n font-weight: normal;\n color: #000;\n}\n\n.headerForeground {\n color: #fff;\n}\n\n.headerForeground a {\n font-weight: normal;\n color: #8cf;\n}\n\n/*}}}*/\n/***\n!General tabs /%=================================================%/\n***/\n/*{{{*/\n\n.tabSelected{\n color: #014;\n background: #eee;\n border-left: 1px solid #ccc;\n border-top: 1px solid #ccc;\n border-right: 1px solid #ccc;\n}\n\n.tabUnselected {\n color: #fff;\n background: #999;\n}\n\n.tabContents {\n color: #014;\n background: #eee;\n border: 1px solid #ccc;\n}\n\n.tabContents .button {\n border: 0;}\n\n/*}}}*/\n/***\n!Sidebar options /%=================================================%/\n~TiddlyLinks and buttons are treated identically in the sidebar and slider panel\n***/\n/*{{{*/\n#sidebar {\n}\n\n#sidebarOptions input {\n border: 1px solid #04b;\n}\n\n#sidebarOptions .sliderPanel {\n background: #8cf;\n}\n\n#sidebarOptions .sliderPanel a {\n border: none;\n color: #04b;\n}\n\n#sidebarOptions .sliderPanel a:hover {\n color: #fff;\n background: #04b;\n}\n\n#sidebarOptions .sliderPanel a:active {\n color: #04b;\n background: #fff;\n}\n/*}}}*/\n/***\n!Message Area /%=================================================%/\n***/\n/*{{{*/\n#messageArea {\n border: 1px solid #841;\n background: #db4;\n color: #014;\n}\n\n#messageArea .button {\n padding: 0.2em 0.2em 0.2em 0.2em;\n color: #014;\n background: #fff;\n}\n\n/*}}}*/\n/***\n!Popup /%=================================================%/\n***/\n/*{{{*/\n.popup {\n background: #18f;\n border: 1px solid #04b;\n}\n\n.popup hr {\n color: #014;\n background: #014;\n border-bottom: 1px;\n}\n\n.popup li.disabled {\n color: #04b;\n}\n\n.popup li a, .popup li a:visited {\n color: #eee;\n border: none;\n}\n\n.popup li a:hover {\n background: #014;\n color: #fff;\n border: none;\n}\n/*}}}*/\n/***\n!Tiddler Display /%=================================================%/\n***/\n/*{{{*/\n.tiddler .defaultCommand {\n font-weight: bold;\n}\n\n.shadow .title {\n color: #866;\n}\n\n.title {\n color: #703;\n}\n\n.subtitle {\n color: #866;\n}\n\n.toolbar {\n color: #04b;\n}\n\n.tagging, .tagged {\n border: 1px solid #eee;\n background-color: #eee;\n}\n\n.selected .tagging, .selected .tagged {\n background-color: #ddd;\n border: 1px solid #bbb;\n}\n\n.tagging .listTitle, .tagged .listTitle {\n color: #014;\n}\n\n.tagging .button, .tagged .button {\n border: none;\n}\n\n.footer {\n color: #ddd;\n}\n\n.selected .footer {\n color: #888;\n}\n\n.sparkline {\n background: #8cf;\n border: 0;\n}\n\n.sparktick {\n background: #014;\n}\n\n.errorButton {\n color: #ff0;\n background: #f00;\n}\n\n.cascade {\n background: #eef;\n color: #aac;\n border: 1px solid #aac;\n}\n\n.imageLink, #displayArea .imageLink {\n background: transparent;\n}\n\n/*}}}*/\n/***\n''The viewer is where the tiddler content is displayed'' /%------------------------------------------------%/\n***/\n/*{{{*/\n\n.viewer .listTitle {list-style-type: none; margin-left: -2em;}\n\n.viewer .button {\n border: 1px solid #db4;\n}\n\n.viewer blockquote {\n border-left: 3px solid #666;\n}\n\n.viewer table {\n border: 2px solid #333;\n}\n\n.viewer th, thead td {\n background: #db4;\n border: 1px solid #666;\n color: #fff;\n}\n\n.viewer td, .viewer tr {\n border: 1px solid #666;\n}\n\n.viewer pre {\n border: 1px solid #fe8;\n background: #ffc;\n}\n\n.viewer code {\n color: #703;\n}\n\n.viewer hr {\n border: 0;\n border-top: dashed 1px #666;\n color: #666;\n}\n\n.highlight, .marked {\n background: #fe8;\n}\n/*}}}*/\n/***\n''The editor replaces the viewer in the tiddler'' /%------------------------------------------------%/\n***/\n/*{{{*/\n.editor input {\n border: 1px solid #04b;\n}\n\n.editor textarea {\n border: 1px solid #04b;\n width: 100%;\n}\n\n.editorFooter {\n color: #aaa;\n}\n\n/*}}}*/
/***\n!Sections in this Tiddler:\n*Generic rules\n**Links styles\n**Link Exceptions\n*Header\n*Main menu\n*Sidebar\n**Sidebar options\n**Sidebar tabs\n*Message area\n*Popup\n*Tabs\n*Tiddler display\n**Viewer\n**Editor\n*Misc. rules\n!Generic Rules /%==============================================%/\n***/\n/*{{{*/\nbody {\n font-size: .75em;\n font-family: arial,helvetica;\n position: relative;\n margin: 0;\n padding: 0;\n}\n\nh1,h2,h3,h4,h5 {\n font-weight: bold;\n text-decoration: none;\n padding-left: 0.4em;\n}\n\nh1 {font-size: 1.35em;}\nh2 {font-size: 1.25em;}\nh3 {font-size: 1.1em;}\nh4 {font-size: 1em;}\nh5 {font-size: .9em;}\n\nhr {\n height: 1px;\n}\n\na{\n text-decoration: none;\n}\n\nol { list-style-type: decimal }\nol ol { list-style-type: lower-alpha }\nol ol ol { list-style-type: lower-roman }\nol ol ol ol { list-style-type: decimal }\nol ol ol ol ol { list-style-type: lower-alpha }\nol ol ol ol ol ol { list-style-type: lower-roman }\nol ol ol ol ol ol ol { list-style-type: decimal }\n/*}}}*/\n/***\n''General Link Styles'' /%-----------------------------------------------------------------------------%/\n***/\n/*{{{*/\n.externalLink {\n text-decoration: underline;\n}\n\n.tiddlyLinkExisting {\n font-weight: bold;\n}\n\n.tiddlyLinkNonExisting {\n font-style: italic;\n}\n\n/* the 'a' is required for IE, otherwise it renders the whole tiddler a bold */\na.tiddlyLinkNonExisting.shadow {\n font-weight: bold;\n}\n/*}}}*/\n/***\n''Exceptions to common link styles'' /%------------------------------------------------------------------%/\n***/\n/*{{{*/\n\n#mainMenu .tiddlyLinkExisting, \n#mainMenu .tiddlyLinkNonExisting,\n#sidebarTabs .tiddlyLinkExisting,\n#sidebarTabs .tiddlyLinkNonExisting{\n font-weight: normal;\n font-style: normal;\n}\n\n/*}}}*/\n/***\n!Header /%==================================================%/\n***/\n/*{{{*/\n\n.header {\n position: relative;\n}\n\n.header a:hover {\n background: transparent;\n}\n\n.headerShadow {\n position: relative;\n padding: 4.5em 0em 1em 1em;\n left: -1px;\n top: -1px;\n}\n\n.headerForeground {\n position: absolute;\n padding: 4.5em 0em 1em 1em;\n left: 0px;\n top: 0px;\n}\n\n.siteTitle {\n font-size: 3em;\n}\n\n.siteSubtitle {\n font-size: 1.2em;\n}\n\n/*}}}*/\n/***\n!Main menu /%==================================================%/\n***/\n/*{{{*/\n#mainMenu {\n position: absolute;\n left: 0;\n width: 10em;\n text-align: right;\n line-height: 1.6em;\n padding: 1.5em 0.5em 0.5em 0.5em;\n font-size: 1.1em;\n}\n\n/*}}}*/\n/***\n!Sidebar rules /%==================================================%/\n***/\n/*{{{*/\n#sidebar {\n position: absolute;\n right: 3px;\n width: 16em;\n font-size: .9em;\n}\n/*}}}*/\n/***\n''Sidebar options'' /%----------------------------------------------------------------------------------%/\n***/\n/*{{{*/\n#sidebarOptions {\n padding-top: 0.3em;\n}\n\n#sidebarOptions a {\n margin: 0em 0.2em;\n padding: 0.2em 0.3em;\n display: block;\n}\n\n#sidebarOptions input {\n margin: 0.4em 0.5em;\n}\n\n#sidebarOptions .sliderPanel {\n margin-left: 1em;\n padding: 0.5em;\n font-size: .85em;\n}\n\n#sidebarOptions .sliderPanel a {\n font-weight: bold;\n display: inline;\n padding: 0;\n}\n\n#sidebarOptions .sliderPanel input {\n margin: 0 0 .3em 0;\n}\n/*}}}*/\n/***\n''Sidebar tabs'' /%-------------------------------------------------------------------------------------%/\n***/\n/*{{{*/\n\n#sidebarTabs .tabContents {\n width: 15em;\n overflow: hidden;\n}\n\n/*}}}*/\n/***\n!Message area /%==================================================%/\n***/\n/*{{{*/\n#messageArea {\nposition:absolute; top:0; right:0; margin: 0.5em; padding: 0.5em;\n}\n\n*[id='messageArea'] {\nposition:fixed !important; z-index:99;}\n\n.messageToolbar {\ndisplay: block;\ntext-align: right;\n}\n\n#messageArea a{\n text-decoration: underline;\n}\n/*}}}*/\n/***\n!Popup /%==================================================%/\n***/\n/*{{{*/\n.popup {\n font-size: .9em;\n padding: 0.2em;\n list-style: none;\n margin: 0;\n}\n\n.popup hr {\n display: block;\n height: 1px;\n width: auto;\n padding: 0;\n margin: 0.2em 0em;\n}\n\n.popup li.disabled {\n padding: 0.2em;\n}\n\n.popup li a{\n display: block;\n padding: 0.2em;\n}\n/*}}}*/\n/***\n!Tabs /%==================================================%/\n***/\n/*{{{*/\n.tabset {\n padding: 1em 0em 0em 0.5em;\n}\n\n.tab {\n margin: 0em 0em 0em 0.25em;\n padding: 2px;\n}\n\n.tabContents {\n padding: 0.5em;\n}\n\n.tabContents ul, .tabContents ol {\n margin: 0;\n padding: 0;\n}\n\n.txtMainTab .tabContents li {\n list-style: none;\n}\n\n.tabContents li.listLink {\n margin-left: .75em;\n}\n/*}}}*/\n/***\n!Tiddler display rules /%==================================================%/\n***/\n/*{{{*/\n#displayArea {\n margin: 1em 17em 0em 14em;\n}\n\n\n.toolbar {\n text-align: right;\n font-size: .9em;\n visibility: hidden;\n}\n\n.selected .toolbar {\n visibility: visible;\n}\n\n.tiddler {\n padding: 0.5em 1em 0em 1em;\n border: 1px #999 solid;\n margin-bottom: 1em;\n}\n\n.missing .viewer,.missing .title {\n font-style: italic;\n}\n\n.title {\n font-size: 1.6em;\n font-weight: bold;\n}\n\n.missing .subtitle {\n display: none;\n}\n\n.subtitle {\n font-size: 1.1em;\n}\n\n/* I'm not a fan of how button looks in tiddlers... */\n.tiddler .button {\n padding: 0.2em 0.4em;\n}\n\n.tagging {\nmargin: 0.5em 0.5em 0.5em 0;\nfloat: left;\ndisplay: none;\n}\n\n.isTag .tagging {\ndisplay: block;\n}\n\n.tagged {\nmargin: 0.5em;\nfloat: right;\n}\n\n.tagging, .tagged {\nfont-size: 0.9em;\npadding: 0.25em;\n}\n\n.tagging ul, .tagged ul {\nlist-style: none;margin: 0.25em;\npadding: 0;\n}\n\n.tagClear {\nclear: both;\n}\n\n.footer {\n font-size: .9em;\n}\n\n.footer li {\ndisplay: inline;\n}\n/***\n''The viewer is where the tiddler content is displayed'' /%------------------------------------------------%/\n***/\n/*{{{*/\n* html .viewer pre {\n width: 99%;\n padding: 0 0 1em 0;\n}\n\n.viewer {\n line-height: 1.4em;\n padding-top: 0.5em;\n}\n\n.viewer .button {\n margin: 0em 0.25em;\n padding: 0em 0.25em;\n}\n\n.viewer blockquote {\n line-height: 1.5em;\n padding-left: 0.8em;\n margin-left: 2.5em;\n}\n\n.viewer ul, .viewer ol{\n margin-left: 0.5em;\n padding-left: 1.5em;\n}\n\n.viewer table {\n border-collapse: collapse;\n margin: 0.8em 1.0em;\n}\n\n.viewer th, .viewer td, .viewer tr,.viewer caption{\n padding: 3px;\n}\n\n.viewer pre {\n padding: 0.5em;\n margin-left: 0.5em;\n font-size: 1.2em;\n line-height: 1.4em;\n overflow: auto;\n}\n\n.viewer code {\n font-size: 1.2em;\n line-height: 1.4em;\n}\n/*}}}*/\n/***\n''The editor replaces the viewer in the tiddler'' /%------------------------------------------------%/\n***/\n/*{{{*/\n.editor {\nfont-size: 1.1em;\n}\n\n.editor input, .editor textarea {\n display: block;\n width: 100%;\n font: inherit;\n}\n\n.editorFooter {\n padding: 0.25em 0em;\n font-size: .9em;\n}\n\n.editorFooter .button {\npadding-top: 0px; padding-bottom: 0px;}\n\n.fieldsetFix {border: 0;\npadding: 0;\nmargin: 1px 0px 1px 0px;\n}\n/*}}}*/\n/***\n!Misc rules /%==================================================%/\n***/\n/*{{{*/\n.sparkline {\n line-height: 1em;\n}\n\n.sparktick {\n outline: 0;\n}\n\n.zoomer {\n font-size: 1.1em;\n position: absolute;\n padding: 1em;\n}\n\n.cascade {\n font-size: 1.1em;\n position: absolute;\n overflow: hidden;\n}\n/*}}}*/
!!The subroutine arguments\nThis does not do what you think.\n{{{\nsub doit\n{\n foreach(@_)\n {\n chomp;\n return "empty" if /^\ss*$/;\n }\n return;\n}\n}}}\n* The elements of {{{@_}}} are aliases for the supplied parameters.\n* The {{{$_}}} variable in the {{{foreach}}} aliases each of the list items we are iterating over.\n* The result is that the newline is removed from each argument up to the first empty line.\n!!The {{{return}}}\nSome books recommend returning false from a subroutine with the following statement.\n{{{\n return undef;\n}}}\n\nThat is {{{false}}} in scalar context. Unfortunately, in list context, it becomes a list containing a single {{{undef}}}. The value of this list is {{{true}}}.\n!!The {{{&}}} sigil\nCalling a subroutine prefixed with the {{{&}}} sigil has a side effect you may not be aware of.\nIf a subroutine is called with the following syntax:\n{{{\n &func;\n}}}\nIt is not called with no parameters, it is called with the {{{@_}}} array of the calling subroutine.
Let's determine what the function {{{doit}}} returns for different values of the arguments.\n\n{{{\nsub doit\n{\n my ($a, $b) = @_;\n return unless $a;\n\n if($a < $b)\n {\n "less";\n }\n elsif($a > $b)\n {\n "greater";\n }\n}\n}}}\n|! {{{$a}}} |! {{{$b}}} |! returns |! why |\n| 0 | don't care | {{{undef}}} or {{{()}}} |{{{return}}} with no arguments returns returns false fo scalar or list context|\n| 5 | 10 | "less" |The string {{{"less"}}} was the last expression executed|\n| 10 | 5 | "greater" |The string {{{"greater"}}} was the last expression executed|\n| 10 | 10 | {{{undef}}} |The last expression executed was {{{$a > $b}}}, which evaluated to {{{false}}}|\n\nThe last may not have been what you expected.\n
* Copy the parameters from {{{@_}}} into {{{my}}} variables for better naming.\n* {{{scalar @_}}} is the number of arguments passed (before you shift any into variables).\n* You can return more than one value from a subroutine by returning a list.\n{{{\n return ( 'yes', 42, undef, 3.1415 );\n}}}\n* If you want to return a //false// value, use a {{{return}}} without any argument. This does the right thing in both list and scalar context.\n{{{\n return;\n}}}\n
* The {{{@_}}} array aliases the supplied arguments.\n** It is possible to modify the supplied arguments using this fact.\n** This does make your code harder to read and is not the normal usage.\n* Perl supports anonymous subroutines.\n{{{\nmy $greeting = sub {\n my $arg = shift;\n print "Hello, $name\sn;"\n};\n$greeting->( "Wade" );\n}}}\n* Perl supports a useful idiom for named parameters\n{{{\nsub is_between\n{\n my %args = (\n high => 100,\n low => 0,\n @_\n );\n\n return $args{low} <= $args{value} and $args{value} <= $args{high};\n}\n\nis_between( value=> $varb, high=> 212, low => 32 );\n}}}
Like most programming languages, Perl supports subroutines.\n{{{\nsub sum\n{\n my $sum = shift;\n foreach my $num (@_)\n {\n $sum += $num;\n }\n return sum;\n}\n}}}\n* The parameters of a subroutine are passed in the standard array {{{@_}}}.\n* {{{return}}} leaves the subroutine and specifies the value to return.\n* If there is no {{{return}}} statement, the value of the last statement executed is returned.\n\nA subroutine is called by name with its arguments in parenthesis.\n{{{\nmy $total = sum( 1, 2, 3, 4, 5, 6, 7, 8, 9 );\n}}}\n* In some older documentation you may have seen the functions called using the {{{&}}} operator, that is no longer necessary.\n\n* [[Subroutine tips]]\n* [[Subroutine tricks]]\n* [[Subroutine gotchas]]\n* [[Subroutine puzzle]]
Any input from the outside world is tainted. If any tainted data is used to affect the system (write to disk or such), Perl exits with a message.\n\nThis prevents accidentally using untrusted data from being used where it might be dangerous.\nThe only way to untaint data is with a regular expression.\n{{{\nif($name_input =~ /^([a-zA-Z. ]+)$/)\n{\n $name = $1;\n}\n}}}\n
If you have a list and want a new list that contains only the unique elements of the list, there are approaches:\n\nIf you don't care about the order of the returned list, this works nicely:\n{{{\nsub uniq\n{\n my %seen = map { $_ => 1 } @_;\n return keys %seen;\n}\n}}}\n\nIf you want the list in the same order as the original, you want the following instead:\n{{{\nsub uniq\n{\n my %seen = ();\n return grep { 0 == $seen{$_}++ } @_;\n}\n}}}\n
Since this is what baffles most people about Perl, let's get it out of the way quickly. Perl has 3 data types\n\n* [[Scalar]] ($)\n* [[List]] (@)\n* [[Hash]] (%)\n\nThe sigil at the front of a variable tells you what kind of data you are extracting from the variable. Usually, it is a '$' because you only want one piece of data at a time.\n\n* {{{$scalar}}} - the value of a scalar\n\n* {{{@array}}} - refers to the whole array\n* {{{$array[0]}}} - refers to the first element of the array\n* {{{@array[0,1]}}} - returns a list of the first two elements of the array\n* {{{$#array}}} - the index of the last element\n* {{{scalar @array}}} - the number of elements in the array\n\n* {{{%hash}}} - refers to the whole hash\n* {{{$hash{key} }}} - refers to an element of the hash\n* {{{@hash{'key1', 'key2'} }}} - returns a list of values associated with two keys\n\n* [[my variable]]\n* [[local variable]]
* performing an exact match on the whole string\n* the position and length of a substring are known\n* looking at multiple fixed position fields\n* working with nested constructs, consider not using regexes (Until Perl 6)\n* dealing with fixed size, binary data
* partial matches in a string\n* //obvious// patterns: numbers, words, whitespace, dates, times, etc.\n* raw text with minor changes: capitalization, plurals, etc.\n* testing for proper formatting\n* recognizing bad input\n* untainting input\n
{{{local}}} variables are a holdover from earlier versions of Perl.\nThey are nothing like local variables in other languages.\n\n* The {{{local}}} operator saves the current value of the specified global variable.\n* When the enclosing scope ends, the saved value is restored.\n* Any code called from the current block sees the localized value of the global.\n\nMost of the time you really want a [[my variable]].
Perl uses the {{{my}}} operator to make lexical variables.\nLexical variables are a lot like local variables in other languages.\nLexical variables are only visible within the scope they are defined. (Well, almost)\n\n{{{\n {\n my $variable = 5;\n }\n # $variable is not visible here\n}}}\n\n[[my variable tricks]]
The one time that {{{my}}} variables don't work like local variables in another language involves a //Closure//.\n\nWhen creating an anonymous subroutine, any lexical variables visible in the scope where the routine was created are bound to the subroutine and live on outside their scope.\n\n{{{\nsub make_counter\n{\n my $counter = 0;\n return sub { return $counter++; }\n}\n\nmy $counter_a = make_counter();\nmy $counter_b = make_counter();\n}}}
Another useful pragma is //diagnostics//. The diagnostics pragma is like //warnings// but with a lot more detail.\n\n{{{\n use strict;\n use warnings;\n use diagnostics;\n}}}
The {{{wantarray}}} operator returns one of three values depending on the context from which it is called.\n\n* {{{1}}} - list context\n* {{{0}}} - scalar context\n* {{{undef}}} - void context