<?xml version="1.0" encoding="UTF-8"?>



<rss version="2.0" xmlns:blogChannel="http://backend.userland.com/blogChannelModule">

    <channel>
        <title>perltutorial</title>
        <link>http://prlmnks.org/list/</link>
        <description>RSS feeds from perlmonks.org</description>
        <language>en</language>
        <ttl>5</ttl>

        

<item>
    <title>Threads: why locking is required when using shared variables (ikegami)</title>
    <link>http://prlmnks.org/html/579444.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/579444.html</guid>

    <description>
        &lt;p&gt;I was recently faced with a thread that used &lt;tt class=&quot;inline_code&quot;&gt;.=&lt;/tt&gt; on a shared variable, and I wondered if that was safe. I figured I&#39;d write up a introductory tutorial on the answer I found. For simplicity, we&#39;ll look at &lt;tt class=&quot;inline_code&quot;&gt;++&lt;/tt&gt; first.&lt;hr&gt;&lt;p&gt;The following code outputs 400,000:&lt;pre class=&quot;block_code&quot;&gt;my $count     = 100_000;my $num_calls = 4;my $sum = 0;sub inc { ++$sum for 1..$count; }inc() for 1..$num_calls;print(&quot;$sum\n&quot;);   # 400000&lt;/pre&gt;&lt;p&gt;If you ran the 4 calls to &lt;tt class=&quot;inline_code&quot;&gt;inc&lt;/tt&gt; in parallel, would the answer still be 400,000? Not likely, if you don&#39;t change &lt;tt class=&quot;inline_code&quot;&gt;inc&lt;/tt&gt;.&lt;pre class=&quot;block_code&quot;&gt;use threads;use threads::shared;my $count     = 100_000;my $num_calls = 4;my $sum : shared = 0;sub inc { ++$sum for 1..$count; }$_-&gt;join for map { threads-&gt;create( \&amp;inc ) } 1..$num_calls;print(&quot;$sum\n&quot;);   # 314813&lt;/pre&gt;&lt;p&gt;That&#39;s because there is a [wp://race condition].&lt;pre class=&quot;block_code&quot;&gt;+=======================+|          CPU          |+-----------+-----------+| thread 1  | thread 2  |+===========+===========+| ...       |           |   T| load $sum |           |   i| inc       |           |   m+-----------+-----------+   e|           | ...       |   ||           | load $sum |   ||           | inc       |   v|           | save $sum ||           | ...       |+-----------+-----------+| save $sum |           || ...       |           |+===========+===========+&lt;/pre&gt;&lt;p&gt;The solution is to protect the [wp://critical section] using a thread synchronization mechanism such as &lt;tt class=&quot;inline_code&quot;&gt;lock&lt;/tt&gt;.&lt;pre class=&quot;block_code&quot;&gt;use threads;use threads::shared;my $count     = 100_000;my $num_calls = 4;my $sum : shared = 0;sub inc { for (1..$count) { lock($sum); ++$sum } }$_-&gt;join for map { threads-&gt;create( \&amp;inc ) } 1..$num_calls;print(&quot;$sum\n&quot;);   # 400000&lt;/pre&gt;&lt;p&gt;Whenever an transformation operation (read &amp;#8658; manipulate &amp;#8658; write) is performed on a shared variable, locking is needed. See [mod://threads::shared] for tools to do this.&lt;p&gt;The program behind the &lt;tt class=&quot;inline_code&quot;&gt;&lt;spoiler&gt;&lt;/tt&gt; below outputs results similar to the following:&lt;pre class=&quot;block_code&quot;&gt;++s     sum = 233564 (expecting 400000)s+=1    sum = 143915 (expecting 400000)c.=l    length = 248149 (expecting 400000)c=c.l   length = 123360 (expecting 400000)&lt;/pre&gt;&lt;p&gt;As you can see, &lt;tt class=&quot;inline_code&quot;&gt;+=&lt;/tt&gt;, &lt;tt class=&quot;inline_code&quot;&gt;.=&lt;/tt&gt; and &lt;tt class=&quot;inline_code&quot;&gt;= .&lt;/tt&gt; are also not atomic. The program can only prove that an operator isn&#39;t atomic (i.e. is interruptable). It cannot prove that an operator is atomic (i.e. is not interruptable). If you&#39;re getting the &quot;expecting&quot; result, try upping &lt;tt class=&quot;inline_code&quot;&gt;$count&lt;/tt&gt; and/or &lt;tt class=&quot;inline_code&quot;&gt;$threads&lt;/tt&gt;.&lt;spoiler&gt;&lt;pre class=&quot;block_code&quot;&gt;use v5.8.0;use strict;use warnings;use threads;use threads::shared;{   my $count   = 100_000;   my $threads = 4;   my $sum : shared = 0;   sub inc {      for (1..$count) {         ++$sum;      }   }   $_-&gt;join      for map { threads-&gt;create( \&amp;inc ) }          0..$threads-1;   print(&quot;++s     sum = $sum (expecting &quot; . ($count*$threads). &quot;)\n&quot;);}{   my $count   = 100_000;   my $threads = 4;   my $sum : shared = 0;   sub inc_assign {      for (1..$count) {         $sum += 1;      }   }   $_-&gt;join      for map { threads-&gt;create( \&amp;inc_assign ) }          0..$threads-1;   print(&quot;s+=1    sum = $sum (expecting &quot; . ($count*$threads). &quot;)\n&quot;);}{   my $count   = 100_000;   my $threads = 4;   my $content : shared = &#39;&#39;;   sub append {      my ($letter) = @_;      for (1..$count) {         $content .= $letter;      }   }   $_-&gt;join      for map { threads-&gt;create( \&amp;append, chr(ord(&#39;a&#39;)+$_) ) }          0..$threads-1;   print(&quot;c.=l    length = &quot; . length($content) .         &quot; (expecting &quot; . ($count*$threads). &quot;)\n&quot;);}{   my $count   = 100_000;   my $threads = 4;   my $content : shared = &#39;&#39;;   sub concatenate {      my ($letter) = @_;      for (1..$count) {         $content = $content . $letter;      }   }   $_-&gt;join      for map { threads-&gt;create( \&amp;concatenate, chr(ord(&#39;a&#39;)+$_) ) }          0..$threads-1;   print(&quot;c=c.l   length = &quot; . length($content) .         &quot; (expecting &quot; . ($count*$threads). &quot;)\n&quot;);}&lt;/pre&gt;&lt;/spoiler&gt;&lt;p&gt;&lt;b&gt;Update&lt;/b&gt;: Added the preface and links to Wikipedia.&lt;p&gt;&lt;small&gt;Added to [Tutorials] by [planetscape] &lt;readmore title=&quot;view votes&quot;&gt;( keep:0 edit:6 reap:0 )&lt;/small&gt;&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>Big-O Notation - What is it good for? (Limbic~Region)</title>
    <link>http://prlmnks.org/html/573138.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/573138.html</guid>

    <description>
        [All],&lt;br /&gt;If you have ever felt that people debating the big-oh notation of some algorithm sound like they are speaking a foreign language, then this tutorial is for you.  You may have even decided to educate yourself by checking out the [wp://Big_o_notation|Wikipedia entry] and have been convinced it was a foreign language.  You are not alone.&lt;p&gt;You may have already read [id://227909] by [dws] which is excellent.  This tutorial will repeat much of the same information in a much more elementary manner as well as go into detail about how useful &lt;i&gt;or not&lt;/i&gt; the notation is.  It is likely I won&#39;t be completely accurate about a number of things in the tutorial.  My hope is that by the end, your understanding of the topic will be sufficient enough that you can understand the corrections others make (&lt;i&gt;as I am sure they will&lt;/i&gt;).&lt;/p&gt;&lt;READMORE&gt;&lt;h4&gt;What Is The Big-O&lt;/h4&gt;This tutorial covers the Big-O as it relates to computer science.  If you were thinking of something else (perhaps Fridays in the Chatterbox), you can stop reading now.  Simply put, it describes how the algorithm scales (&lt;i&gt;performs&lt;/i&gt;) in the worst case scenario as it is is run with more input.  Since my simple explanation may not be simple enough - let me give an example.  If we have a sub that searches an array item by item looking for a given element, the scenario that the Big-O describes is when the target element is last (or not present at all).  This particular algorithm is O(N) so the same algorithm working on an array with 25 elements should take approximately 5 times longer than an array with 5 elements.&lt;p&gt;It is easy to lose sight of the fact that there is more to consider about an algorithm other than how fast it runs.  The Big-O can also be used to describe other behavior such as memory consumption.  We often optimize by trading memory for time.  You may need to choose a slower algorithm because it also consumes less of a resource that you need to be frugal with.&lt;/p&gt;&lt;h4&gt;What The Big-O Is Not&lt;/h4&gt;&lt;b&gt;Constants:&lt;/b&gt;  The Big-O is not concerned with factors that do not change as the input increases.  Let me give an example that may be suprising.  Let&#39;s say we have an algorithm that needs to compare every element in an array to every other element in the array.  A simple implementation may look like:&lt;pre class=&quot;block_code&quot;&gt;for my $i (0 .. $#array) {    for my $j (0 .. $#array) {        next if $j == $i;        # Compare $i, $j    }}&lt;/pre&gt;This is O(N^2).  After a little bit of testing we decide that this is far too slow, so we make a little optimization.&lt;pre class=&quot;block_code&quot;&gt;for my $i (0 .. $#array - 1) {    for my $j ($i + 1 .. $#array) {        # Compare $i, $j    }}&lt;/pre&gt;We have just cut our run time in half - YAY!  Guess what, the Big-O has stayed the same O(N^2).  This is because N^2 / 2 only has one variable part.  The &lt;i&gt;divided by 2&lt;/i&gt; does not affect how the algorithm scales.  If you remember a little linear algebra, the slope of a line is the change in height (execution time) as the length (size of input) increases.  While the second algorithm&#39;s line will always be half as high as the first, it&#39;s slope will be exactly the same.&lt;p&gt;&lt;b&gt;Implementation Details:&lt;/b&gt;  The Big-O is an uncaring cold-hearted jerk.  It does not care if you can&#39;t afford to buy the extra RAM needed for your problem and have to resort to tying your hash to disk.  You are on your own.  It also doesn&#39;t care that the data structure you would need to implement to achieve O(Log Log N) is so complex you will never be able to maintain it.  In a nutshell, the Big-O lives in the land of theory and doesn&#39;t care very much about the real world.&lt;/p&gt;&lt;h4&gt;What The Big-O Is Good For&lt;/h4&gt;The good news is that the Big-O belongs to an entire family of notation.  This tutorial will not cover it but family members include describing the average and best cases.  It also serves as a good indicator of what algorithm to use once you take your individual circumstances into consideration.  Let me give a contrived example:&lt;p&gt;Let&#39;s consider using cacheing as an optimization.  In theory, the Big-O is going to ignore it saying your input is all different and you will never benefit from it.  In reality, you test it and discover that you have a 60% hit rate.  You do a little more experimenting and discover that the input size required for a more complex algorithm to be faster is larger than your &lt;i&gt;real&lt;/i&gt; maximum input size.  This all despite the more complex alorithm having a more favorable Big-O.&lt;/p&gt;&lt;p&gt;In a nutshell, the Big-O of a given algorithm combined with the specific problem knowledge is a great way to choose the best algorithm for your situation.&lt;/p&gt;&lt;h4&gt;What Do Those Symbols Mean?&lt;/h4&gt;So by this point you should realize that Big-O (theory) without context (real world) is not very useful.  You are now armed with the knowledge necessary to start using Big-O as the mercenary it is.  Ok Big-O, what exactly do you mean that algorithm is O(N Log N)?  I am going to duck at this point and suggest you read the node by [dws] or the Wikipedia entry I linked to earlier.  You may now be wondering if Big-O is really inanimate, perhaps even an abstract concept and not at all real as I have made it out to be.  If so, how then can you determine the Big-O of a given algorithm?  [http://algo.inria.fr/AofA/|Analysis of algorithms] is not for the faint of heart, so I must once again duck.&lt;/READMORE&gt;&lt;p&gt;I have not really added anything to any of the other links I referenced.  I do hope however that I have put it in plain enough english to be understood by even the most extreme novice.  I welcome those more knowledgeable than myself to add corrections as well as provide additional content.  I would only ask that you do so in the same spirit of this tutorial (&lt;i&gt;understandable by non-CS majors&lt;/i&gt;).&lt;/p&gt;&lt;small&gt;&lt;small&gt;Also see [id://25833] by [jeffa]&lt;/small&gt;&lt;/small&gt;&lt;div class=&quot;pmsig&quot;&gt;&lt;div class=&quot;pmsig-180961&quot;&gt;&lt;p&gt;Cheers - [Limbic~Region|L~R]&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
    </description>
</item>

        

<item>
    <title>Common Causes for &quot;Modification of a read-only value attempted&quot; (imp)</title>
    <link>http://prlmnks.org/html/570712.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/570712.html</guid>

    <description>
        You tried, directly or indirectly, to change the value of aconstant. This type of error frequently occurs at a distance and is difficult to trace. The magic of $_ is often involved, but is not responsible.&lt;p&gt;&lt;p&gt;Common causes:&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;#loop_lvalue&quot;&gt;  Treating a loop variable as an lvalue&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#map_grep&quot;&gt;Modifying $_ inside foreach, map or grep&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#param_lvalue&quot;&gt;  Modifying elements of @_ directly&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#sort_modify&quot;&gt;  Modifying $a or $b inside sort&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#sort_vivify&quot;&gt;  Autovivifying $a or $b inside sort&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#default_unlocalized&quot;&gt;  Modifying an unlocalized $_&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;a name=&quot;loop_lvalue&quot;&gt;  &lt;h4&gt;Treating a loop variable as an lvalue&lt;/h4&gt;&lt;/a&gt;&lt;pre class=&quot;block_code&quot;&gt;for my $x (1,2) {  $x++;}&lt;/pre&gt;In this example $x is aliased to the constant &#39;1&#39;, so when the loop body attempts to increment $x an error is triggered. See &lt;a href=&quot;#lists_with_constants&quot;&gt;Lists With Constant Values&lt;/a&gt; for more details.&lt;a name=&quot;map_grep&quot;&gt;&lt;h4&gt;Modifying $_ inside [doc://perlsyn#Foreach-Loops-for-foreach|foreach], [doc://map] or [doc://grep]&lt;/h4&gt;&lt;/a&gt;&lt;pre class=&quot;block_code&quot;&gt;for (1,2) {  chomp;}for (&quot;foo&quot;, @list) {  s/foo/bar/;}@array = map  { $_++ } (1,2);@array = grep { $_++ } (1,2);&lt;/pre&gt;In all of these examples $_ is aliased to a constant, and when the loop body attempts to modify $_ an error is triggered. See &lt;a href=&quot;#lists_with_constants&quot;&gt;Lists With Constant Values&lt;/a&gt; for more details.&lt;a name=&quot;param_lvalue&quot;&gt;&lt;h4&gt;Modifying elements of @_ directly&lt;/h4&gt;&lt;/a&gt;&lt;pre class=&quot;block_code&quot;&gt;sub incr {  $_[0]++;}my $n = 1;incr($n); # goodincr(1);  # bad&lt;/pre&gt;Modifying elements of &lt;tt class=&quot;inline_code&quot;&gt;@_&lt;/tt&gt; directly allows you tomodify the variable that was passed to the function. For example, in the above example &lt;i&gt;$n&lt;/i&gt; is now 2. But an error will occur when a constant is passed, as in the second call.&lt;a name=&quot;sort_modify&quot;&gt;&lt;h4&gt;Modifying $a or $b inside [doc://sort]&lt;/h4&gt;&lt;/a&gt;&lt;pre class=&quot;block_code&quot;&gt;@array = sort { $a++ } (1,2);&lt;/pre&gt;It is permissible (but ill-advised) to modify $a and $b within sort. However, modifying a constant that is aliased to $a or $b is still an error.&lt;a name=&quot;sort_vivify&quot;&gt;&lt;h4&gt;Autovivifying $a or $b inside [doc://sort]&lt;/h4&gt;&lt;/a&gt;&lt;pre class=&quot;block_code&quot;&gt;my @bad;$bad[0] = [1];$bad[2] = [2];@bad = sort {$a-&gt;[0] &lt;=&gt; $b-&gt;[0]} @bad;&lt;/pre&gt;The variables $a and $b are aliased to each item in the list being sorted, and as such modifying them is possible - but will cause an error if the current element is unmodifiable. A common cause of this is sorting an array of references when where the list has a gap. In this situation $a will be undef, and autovivification by dereferencing will trigger an error.&lt;a name=&quot;default_unlocalized&quot;&gt;&lt;h4&gt;Modifying an unlocalized $_&lt;/h4&gt;&lt;/a&gt;&lt;pre class=&quot;block_code&quot;&gt;for (1,2) {  my $data = prompt_user();}sub prompt_user {   print &quot;Enter a number\n&quot;;   while (&lt;STDIN&gt;) {     # Do stuff   }}&lt;/pre&gt;This example will cause an error because the [doc://perlsyn#Foreach-Loops-for-foreach|for] loop aliases $_ to the literal &#39;1&#39;, and then calls prompt_user which attempts to read a line from STDIN and store it in $_ - which is still aliased to &#39;1&#39;.&lt;p&gt;The error will also occur in this simplified scenario:&lt;pre class=&quot;block_code&quot;&gt;for (1,2) {    while (&lt;STDIN&gt;) {    }}&lt;/pre&gt;&lt;h3&gt;Guidelines to avoid read-only errors:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;Don&#39;t treat loop variables as a lvalue if there is any chance a constant value will be included&lt;/li&gt;&lt;li&gt;Don&#39;t modify an unlocalized $_&lt;/li&gt;&lt;li&gt;Don&#39;t modify $_ inside map or grep&lt;/li&gt;&lt;li&gt;Don&#39;t modify $a or $b inside sort&lt;/li&gt;&lt;li&gt;Don&#39;t dereference $a or $b inside sort without checking that they exist and are references&lt;/li&gt;&lt;li&gt;Don&#39;t use $_ for the loop variable unless it is a very trivial loop&lt;/li&gt;&lt;li&gt;Don&#39;t modify elements of @_ directly&lt;/li&gt;&lt;/ol&gt;&lt;hr&gt;&lt;h3&gt;Notes&lt;/h3&gt;&lt;a name=&quot;lists_with_constants&quot;&gt;&lt;h4&gt;Lists With Constant Values&lt;/h4&gt;&lt;/a&gt;Within the context of this document the important thing to understand is what expressions result in modifiable objects.The following expressions have constants in them:&lt;pre class=&quot;block_code&quot;&gt;$_++ for (1,2);$_++ for (1,@array);@array = map {$_++} (1,@array);&lt;/pre&gt;And the following are safe:&lt;pre class=&quot;block_code&quot;&gt;my @array = (1,2);for (@array) {  $_++;}&lt;/pre&gt;&lt;pre class=&quot;block_code&quot;&gt;my ($x,$y) = (1,2);for ($x,$y) {  $_++;}&lt;/pre&gt;For an explanation of lists versus arrays I recommend the following:&lt;ul&gt;&lt;li&gt;[id://451421]&lt;/li&gt;&lt;li&gt;[href://http://japhy.perlmonk.org/articles/pm/2000-02.html|&quot;List&quot; Is a Four-Letter Word]&lt;/li&gt;&lt;/ul&gt;
    </description>
</item>

        

<item>
    <title>mod_perl / Apache::Registry accidental closures (imp)</title>
    <link>http://prlmnks.org/html/562746.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/562746.html</guid>

    <description>
        When working with Apache::Registry it is very easy to create accidental closures.&lt;br&gt;This is due to the way Apache::Registry makes a fake package for your script, as I&#39;ll demonstrate in this tutorial.&lt;p&gt;The only indication that something is amiss (other than the unpredictable behaviour) will be the following line in your error log: &lt;i&gt;Variable &quot;$foo&quot; will not stay shared at ...&lt;/i&gt;&lt;p&gt;The following code demonstrates the problem with accidental closures when using Apache::Registry.&lt;pre class=&quot;block_code&quot;&gt;use strict;use warnings;my $foo = 5;print &quot;Content-type: text/plain\n&quot;;print &quot;Content-disposition: inline; filename=foo.txt\n\n&quot;;printf &quot;Package: %s\n&quot;, __PACKAGE__;printf &quot;[%s] Before: %s\n&quot;, $$, $foo;badness(5);printf &quot;[%s] After: %s\n&quot;, $$, $foo;sub badness {    my $val = shift;    printf &quot;[%s] badness: %s\n&quot;, $$, $foo;    $foo += $val;}&lt;/pre&gt;&lt;p&gt;Apache::Registry will take the above code and create a new package for it based on the ServerName and the name of the script, and then wrap the code in a sub handler {} block.&lt;p&gt;If your script is running on &quot;foo.com&quot; and is named &quot;test.pl&quot;, then this is what the above code will look like after Apache::Registry is done:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;package Apache::ROOTfoo_2ecom::test_2epl;use Apache qw(exit);sub handler {#line 1 /www/foo.com/test.pluse strict;use warnings;my $foo = 5;print &quot;Content-type: text/plain\n&quot;;print &quot;Content-disposition: inline; filename=foo.txt\n\n&quot;;printf &quot;Package: %s\n&quot;, __PACKAGE__;printf &quot;[%s] Before: %s\n&quot;, $$, $foo;badness(5);printf &quot;[%s] After: %s\n&quot;, $$, $foo;sub badness {    my $val = shift;    printf &quot;[%s] badness: %s\n&quot;, $$, $foo;    $foo += $val;}}&lt;/pre&gt;&lt;u&gt;First run:&lt;/u&gt;&lt;pre class=&quot;block_code&quot;&gt;Package: Apache::ROOTfoo_2ecom::test_2epl[13520] Before: 5[13520] badness: 5[13520] After: 10&lt;/pre&gt;&lt;u&gt;Second:&lt;/u&gt;&lt;pre class=&quot;block_code&quot;&gt;Package: Apache::ROOTfoo_2ecom::test_2epl[19331] Before: 5[19331] badness: 5[19331] After: 10&lt;/pre&gt;&lt;u&gt;Third:&lt;/u&gt;&lt;pre class=&quot;block_code&quot;&gt;Package: Apache::ROOTfoo_2ecom::test_2epl[19331] Before: 5[19331] badness: 10[19331] After: 5&lt;/pre&gt;&lt;u&gt;Fourth:&lt;/u&gt;&lt;pre class=&quot;block_code&quot;&gt;Package: Apache::ROOTfoo_2ecom::test_2epl[19331] Before: 5[19331] badness: 15[19331] After: 5&lt;/pre&gt;Notice how the number within the badness sub is increasing for each process, but the $foo that is seen by the instance script is never modified after &#39;badness&#39; after the first execution for that process.&lt;p&gt;This is because the badness function is actually an inner function now,and it keeps a reference to the instance of $foo that was created for the first run.&lt;p&gt;&lt;b&gt;Edit - example of how to avoid this issue added, per rhesa&#39;s suggestion&lt;/b&gt;&lt;br&gt;&lt;p&gt;Thankfully it is easy to avoid these problems once you know why they occur.&lt;br&gt;Tips:&lt;ul&gt;&lt;li&gt;Keep your toplevel script minimal&lt;/li&gt;&lt;li&gt;Subroutines should only use the variables that were passed&lt;/li&gt;&lt;li&gt;Encapsulate behaviour in supporting objects&lt;/li&gt;&lt;/ul&gt;Example of a working alternative:&lt;pre class=&quot;block_code&quot;&gt;use strict;use warnings;my $foo = 5;print &quot;Content-type: text/plain\n&quot;;print &quot;Content-disposition: inline; filename=foo.txt\n\n&quot;;printf &quot;Package: %s\n&quot;, __PACKAGE__;printf &quot;[%s] Before: %s\n&quot;, $$, $foo;badness(\$foo, 5);badness(\$foo, 5);printf &quot;[%s] After: %s\n&quot;, $$, $foo;sub badness {    my ($foo,$val) = @_;    printf &quot;[%s] badness: %s\n&quot;, $$, $$foo;    $$foo += $val;}&lt;/pre&gt;
    </description>
</item>

        

<item>
    <title>mbito de variables en Perl: lo bsico (Hue-Bond)</title>
    <link>http://prlmnks.org/html/559011.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/559011.html</guid>

    <description>
        &lt;p&gt;&lt;small&gt;Translated to spanish from [id://23317]&#39;s original [id://66677].&lt;/small&gt;&lt;/p&gt;&lt;h1&gt;mbito&lt;/h1&gt;&lt;p&gt;Una de las cosas necesarias para dominar Perl es cmo manejar los mecanismos de mbito que te ofrece. Que queremos globales? Las tenemos. Que queremos evitar &quot;colisiones&quot; (dos variables con el mismo nombre pisndose una a la otra)? Podemos, y hay ms de una forma de conseguirlo. Pero las reglas de mbito de Perl no son siempre tan claras, y no es slo la diferencia entre &lt;tt&gt;my&lt;/tt&gt; y &lt;tt&gt;local&lt;/tt&gt; lo que hace tropezar a la gente, aunque aclarar eso es uno de mis objetivos.&lt;/p&gt;&lt;p&gt;He aprendido mucho de &lt;a href=&quot;http://perl.plover.com/FAQs/Namespaces.html&quot;&gt;Coping with scoping&lt;/a&gt; y de varios libros de Perl (por ejemplo, &lt;a href=&quot;http://www.perlmonks.org/?node=Effective%20Perl%20Programming&quot;&gt;Effective Perl Programming&lt;/a&gt;), por lo que debo dar crdito a sus autores ([Dominus] por el primero, y Joseph N. Hall y [merlyn] por el segundo). [Dominus] tambin ha hecho varias correcciones a los errores (algunos de ellos notables) de una versin anterior de este tutorial, as que l debera considerarse como mnimo el segundo autor (N del T: aunque [Dominus] no est de acuerdo con esto). Sin embargo la documentacin que viene con tu versin de Perl es la ms actualizada que puedes consultar, as que no dudes en usar &lt;tt&gt;perldoc perlop&lt;/tt&gt; y &lt;tt&gt;perldoc -f foo&lt;/tt&gt; en tu propio sistema.&lt;/p&gt;&lt;h3&gt;Resumen&lt;/h3&gt;&lt;p&gt;S, al principio...&lt;/p&gt;&lt;ul&gt;  &lt;li&gt;&lt;tt&gt;my&lt;/tt&gt; proporciona mbito lxico; una variable declarada con &lt;tt&gt;my&lt;/tt&gt; slo es visible en el bloque en que ha sido declarada.&lt;/li&gt;  &lt;li&gt;Los bloques de cdigo son trozos delimitados por llaves { }. Un archivo tambin se considera un bloque.&lt;/li&gt;  &lt;li&gt;Usar &lt;tt&gt;use vars qw(&amp;#91;nombres de variables&amp;#93;)&lt;/tt&gt; o &lt;tt&gt;our (&amp;#91;nombres de variables&amp;#93;)&lt;/tt&gt; para crear globales.&lt;/li&gt;  &lt;li&gt;&lt;tt&gt;local&lt;/tt&gt; guarda el valor de una global y lo sustituye por un valor nuevo a efectos del cdigo que est en el bloqueactual y al que llamemos desde tal bloque.&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Espacios de nombres&lt;/h2&gt;&lt;p&gt;Una de las ideas bsicas, aunque no es necesario dominarla para muchos programas, es la de &lt;i&gt;espacios de nombres&lt;/i&gt;. Las variables globales (las que no se declaran con &lt;tt&gt;my&lt;/tt&gt;) estn en un paquete. Los paquetes proporcionan &lt;i&gt;espacios de nombres&lt;/i&gt;, que voy a explicar usando como metfora los apellidos. En los pases de habla hispana, &quot;Roberto&quot; es un nombre bastante comn, as que es posible que conozcamos a ms de un &quot;Roberto&quot; (asumiendo que vivimos en uno de estos pases). Normalmente, para los humanos, el contexto de la conversacin basta para que nuestra audiencia sepa de qu &quot;Roberto&quot; estamos hablando (en el vestbulo de la piscina, &quot;Roberto&quot; es el que controla de dardos; pero en el trabajo &quot;Roberto&quot; es el director de la empresa).&lt;/p&gt;&lt;p&gt;Por supuesto, estas personas tambin tienen &lt;i&gt;apellidos&lt;/i&gt; (pero existen personas distintas con el mismo apellido, as que despus de todo esta metfora no es perfecta), y si quisiramos ser explcitos podramos aadirlos para que quien nos oye sepa de qu &quot;Roberto&quot; hablamos. $Garcia::Roberto es una cosa distinta de $Gonzalez::Roberto. Cuando tenemos dos variables distintas con el mismo &quot;nombre de pila&quot;, podemos referirnos a cualquiera de ellas, sin importar el lugar del cdigo en que nos encontremos, usando el nombre completo de la variable.&lt;/p&gt;&lt;p&gt;Se usa el operador &lt;tt&gt;package&lt;/tt&gt; para cambiar el paquete actual. Cuando usamos &lt;tt&gt;package Garcia&lt;/tt&gt; en el programa, estamos, en efecto, diciendo que todas las variables y funciones no calificadas (es decir, que no tienen &quot;apellido&quot; explcito) deben ser entendidas como si estuvieran en el paquete Garcia. Es como decir &quot;en esta parte del programa, voy a hablar de la familia Garcia&quot;.&lt;/p&gt;&lt;p&gt;De forma implcita, hay un &lt;tt&gt;package main&lt;/tt&gt; al principio de los programas, esto es, excepto que declaremos explcitamente un paquete distinto, todas las variables que se declaren (teniendo en cuenta el uso de &lt;tt&gt;my&lt;/tt&gt;) estarn en &lt;tt&gt;main&lt;/tt&gt;. A las variables que estn en un paquete se les llama, y con razn, &quot;globales de paquete&quot;, porque se puede acceder a ellas sin ms desde todos los operadores y subrutinas que estn en tal paquete (y si somos explcitos con sus nombres, tambin son accesibles desde fuera de l).&lt;/p&gt;&lt;p&gt;Usar paquetes hace que acceder a las variables sea como moverse en distintos crculos. Por ejemplo, en el trabajo, se entiende que &quot;Roberto&quot; es &quot;Roberto Szywiecki&quot;, el jefe. En la piscina, &quot;Roberto&quot; es &quot;Roberto Yamauchi&quot;, el experto en dardos. Aqu tenemos un pequeo programa para mostrar el uso de paquetes:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perl -wpackage Szywiecki;$Robert = &quot;el jefe&quot;;sub terminate {  my $name = shift;  print &quot;$Robert ha despedido a ${name}\n&quot;;}terminate(&quot;arturo&quot;); # muestra &quot;el jefe ha despedido a arturo&quot;package main;# terminate(&quot;arturo&quot;); # produce un error si se descomenta__OUTPUT__el jefe ha despedido a arturo&lt;/pre&gt;&lt;p&gt;El nombre completo de la variable &lt;tt&gt;$Robert&lt;/tt&gt; es &lt;tt&gt;$Szywiecki::Robert&lt;/tt&gt; (ntese que el &lt;tt&gt;$&lt;/tt&gt; se desplaza al principio, antes del nombre del paquete, indicando que este es el escalar  &lt;tt&gt;Robert&lt;/tt&gt; que est en el paquete &lt;tt&gt;Szywiecki&lt;/tt&gt;). Para el cdigo y, ms importante, las subrutinas del paquete &lt;tt&gt;Szywiecki&lt;/tt&gt;, un &lt;tt&gt;$Robert&lt;/tt&gt; sin calificar se refiere a &lt;tt&gt;$Szywiecki::Robert&lt;/tt&gt; -- &lt;i&gt;excepto&lt;/i&gt; que &lt;tt&gt;$Robert&lt;/tt&gt; haya sido &quot;enmascarado&quot; por una declaracin &lt;tt&gt;my&lt;/tt&gt; o &lt;tt&gt;local&lt;/tt&gt; (hablaremos de esto despus).&lt;/p&gt;&lt;p&gt;Ahora, al hacer &lt;tt&gt;use strict&lt;/tt&gt; (y se debera! consulta [strict.pm] por ejemplo), tendremos que declarar todas esas variables globales antes de poder usarlas, EXCEPTO que querramos usar siempre sus nombres completos. Esa es la razn por la que la segunda llamada a &lt;tt&gt;terminate&lt;/tt&gt; fallara si  la descomentramos. Perl espera encontrar una subrutina &lt;tt&gt;terminate&lt;/tt&gt; en el paquete &lt;tt&gt;main&lt;/tt&gt;, pero no la hemos definido. Es decir, esto:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perl -wuse strict;$Robert = &quot;el jefe&quot;;  # error!print &quot;\$Robert = $Robert\n&quot;;&lt;/pre&gt;&lt;p&gt;producir un error, mientras que si ponemos el nombre entero (recordando que existe un &lt;tt&gt;package main&lt;/tt&gt; implcito), no hay problema:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perl -wuse strict;$main::Robert = &quot;el jefe&quot;;print &quot;\$main::Robert = $main::Robert\n&quot;;&lt;/pre&gt;&lt;p&gt;Para satisfacer a &lt;tt&gt;strict &#39;vars&#39;&lt;/tt&gt; (la parte de &lt;tt&gt;strict&lt;/tt&gt; que se encarga de las declaraciones de variables), tenemos dos opciones; producen resultados distintos y una de ellas slo est disponible en Perl 5.6.0 y ms recientes:&lt;/p&gt;&lt;ol&gt;  &lt;li&gt;El operador &lt;tt&gt;our ($foo, $bar)&lt;/tt&gt; (en Perl 5.6.0 y superiores) declara &lt;tt&gt;$foo&lt;/tt&gt; como una variable en el paquete actual.&lt;/li&gt;  &lt;li&gt;&lt;tt&gt;use vars qw($foo $bar)&lt;/tt&gt; (versiones anteriores, pero todava funciona en 5.6) le dice a &lt;tt&gt;strict &#39;vars&#39;&lt;/tt&gt; que es correcto usar estas variables sin calificarlas del todo.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Una de las diferencias entre &lt;tt&gt;our&lt;/tt&gt; y el ms antiguo &lt;tt&gt;use vars&lt;/tt&gt; es que &lt;tt&gt;our&lt;/tt&gt; proporciona &lt;i&gt;mbito lxico&lt;/i&gt; (ms acerca de esto en la seccin de &lt;tt&gt;my&lt;/tt&gt;, ms abajo).&lt;/p&gt;&lt;p&gt;Otra diferencia es que con &lt;tt&gt;use vars&lt;/tt&gt;, debemos usar un array de &lt;i&gt;nombres&lt;/i&gt; de variables, no las variables propiamente dichas (tal como con &lt;tt&gt;our&lt;/tt&gt;). Ambos mecanismos nos permiten usar globales al mismo tiempo que mantenemos uno de los principales beneficios de &lt;tt&gt;strict &#39;vars&#39;&lt;/tt&gt;: el estar protegidos de crear variables accidentalmente si nos equivocamos al teclear. &lt;tt&gt;strict &#39;vars&#39;&lt;/tt&gt; exige que las variables se declaren explcitamente (como diciendo &quot;estas son las globales que voy a usar&quot;). Los dos mecanismos permiten hacer esto con globales de paquete.&lt;/p&gt;&lt;p&gt;Algo que debemos tener en cuenta (que es potencialmente algo malo, dependiendo de lo fantico que uno sea de la privacidad&quot;) es que las variables globales no son slo globales a ese paquete, sino que son accesibles desde &lt;i&gt;cualquier parte del cdigo&lt;/i&gt;, siempre que se usen sus nombres completos. Podemos hablar de Roberto, el experto de dardos, en el trabajo si decimos &quot;Roberto Yamauchi&quot; (en este cdigo no uso &lt;tt&gt;strict&lt;/tt&gt; por brevedad):&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perl -wpackage Szywiecki;$Robert = &quot;el jefe&quot;;package PoolHall;$Robert = &quot;el experto en dardos&quot;;package Szywiecki; # a trabajar otra vez!print &quot;Aqu en el trabajo, &#39;Robert&#39; es $Robert, pero en la piscina, &#39;Robert&#39; es $PoolHall::Robert\n&quot;;__OUTPUT__Aqu en el trabajo, &#39;Robert&#39; es el jefe, pero en la piscina, &#39;Robert&#39; es el experto en dardos&lt;/pre&gt;&lt;p&gt;Lo veis? Entender los paquetes no es tan difcil. En trminos generales, un paquete es como una familia de variables (y de subrutinas! el nombre completo de aquel &lt;tt&gt;terminate&lt;/tt&gt; en un ejemplo anterior es &lt;tt&gt;&amp;Szywiecki::terminate&lt;/tt&gt; -- lo mismo sirve para hashes y arrays, por supuesto).&lt;/p&gt;&lt;h2&gt;&lt;tt&gt;my&lt;/tt&gt; (y un poco ms sobre &lt;tt&gt;our&lt;/tt&gt;) &lt;i&gt;a.k.a&lt;/i&gt; mbito lxico&lt;/h2&gt;&lt;p&gt;Las variables declaradas con &lt;tt&gt;my&lt;/tt&gt; no son globales, aunque pueden actuar como tales. Uno de los usos principales de &lt;tt&gt;my&lt;/tt&gt; es operar con una variable que slo sirva en un bucle o subrutina, pero desde luego que hay muchos ms. He aqu algunos conceptos acerca de &lt;tt&gt;my&lt;/tt&gt;:&lt;/p&gt;&lt;ul&gt;  &lt;li&gt;El mbito de una variable &lt;tt&gt;my&lt;/tt&gt; es un &lt;i&gt;bloque&lt;/i&gt; de cdigo.&lt;/li&gt;  &lt;li&gt;Un bloque se define normalmente con llaves { }, pero en lo que a Perl concierne, un archivo tambin es un bloque.&lt;/li&gt;  &lt;li&gt;Las variables declaradas con &lt;tt&gt;my&lt;/tt&gt; &lt;i&gt;&lt;b&gt;no pertenecen a ningn paquete&lt;/b&gt;&lt;/i&gt;, slo &quot;pertenecen&quot; a su bloque.&lt;/li&gt;  &lt;li&gt;Aunque podemos dar nombre a los bloques (por ejemplo, &lt;tt&gt;BEGIN&lt;/tt&gt;), no podemos calificar el nombre del bloque para acceder a la variable &lt;tt&gt;my&lt;/tt&gt;.&lt;/li&gt;  &lt;li&gt;Las variables &lt;tt&gt;my&lt;/tt&gt; a nivel de archivo son las que se declaran en un archivo pero fuera de un bloque de cdigo.&lt;/li&gt;  &lt;li&gt;No se puede acceder a una variable &lt;tt&gt;my&lt;/tt&gt; de archivo desde fuera del archivo en que se declare (&lt;i&gt;excepto&lt;/i&gt; que sea el valor de retorno de una subrutina, por ejemplo).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Mientras slo escribamos programas de un solo archivo (por ejemplo, los que no importan mdulos), algunos de estos conceptos no importan mucho. Pero si estamos interesados en privacidad y encapsulacin (por ejemplo, si escribimos mdulos), tendremos que entender todas esas cosas.&lt;/p&gt;&lt;p&gt;He aqu un programa comentado para explicar algunas:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perl -wuse strict;#recordemos que estamos en el paquete mainuse vars qw($foo);$foo = &quot;Yo!&quot;; # damos valor a $main::fooprint &quot;\$foo: $foo\n&quot;; # muestra &quot;Yo!&quot;my $foo = &quot;Hey!&quot;; # variable my a nivel de archivoprint &quot;\$foo: $foo\n&quot;; # muestra &quot;Hey!&quot; -- la variable nueva &#39;pisa&#39; a la vieja{ # comenzamos un bloque   my $foo = &quot;Yacht-Z&quot;;     print &quot;\$foo: $foo\n&quot;;   # muestra &quot;Yacht-Z&quot; -- hay una nueva variable $foo visible  print &quot;\$main::foo: $main::foo\n&quot;;  # todava podemos ver $main::foo  subroutine();   } # fin del bloqueprint &quot;\$foo: $foo\n&quot;; # nuestra variable $foo a nivel de archivo se ve otra vez!print &quot;\$main::foo: $main::foo\n&quot;; # $main::foo todava est aqusub subroutine {  print &quot;\$foo: $foo\n&quot;; # muestra &quot;Hey!&quot;  # Por qu? porque la variable declarada en el bloque sin nombre est en    # su mbito -- ahora tenemos otras llaves distintas rodeando esto. Pero la  # variable de archivo todava est en mbito, y todava &quot;pisa&quot; a la  # declaracin de $main::foo.}package Bar;print &quot;\$foo: $foo\n&quot;; # muestra &quot;Hey!&quot; -- la variable my todava es visible# si no hubiramos hecho la declaracin arriba, esto provocara un error: el# intrprete nos dira que Bar::foo no ha sido definida.__OUTPUT__   $foo: Yo!      $foo: Hey!     $foo: Yacht-Z  $main::foo: Yo!$foo: Hey!$foo: Hey!$main::foo: Yo!  $foo: Hey!&lt;/pre&gt;&lt;p&gt;Tal como la parte de abajo del ejemplo nos dice, dado que no estn en ningn paquete, las variables &lt;tt&gt;my&lt;/tt&gt; &lt;i&gt;pueden ser&lt;/i&gt; visibles incluso aunque hayamos declarado un paquete nuevo, &lt;i&gt;dado que el bloque de cdigo es el archivo&lt;/i&gt; (al menos en este ejemplo).&lt;/p&gt;&lt;p&gt;Este ejemplo usa un bloque sin nombre, no hay estructura de control asociada (por ejemplo &lt;tt&gt;if&lt;/tt&gt; o &lt;tt&gt;while&lt;/tt&gt;). Pero de ser as tampoco habra diferencias.&lt;/p&gt;&lt;p&gt;Las variables &lt;tt&gt;my&lt;/tt&gt; de archivo SON accesibles desde los bloques definidos en ese archivo (tal como el ejemplo muestra), esta es una manera de la que pueden actuar como globales. Si, no obstante, &lt;tt&gt;subroutine&lt;/tt&gt; se hubiera definido en otro archivo, tendramos un error en tiempo de ejecucin. Una vez sabemos cmo funciona &lt;tt&gt;my&lt;/tt&gt;, podemos saber, slo fijndonos en la sintaxis del archivo, dnde va a ser visible. Esta es una razn por la que el mbito que proporciona se llama &quot;lxico&quot;. En esto, &lt;tt&gt;use vars&lt;/tt&gt; y el nuevo operador &lt;tt&gt;our&lt;/tt&gt; difieren: si ponemos &lt;tt&gt;our $foo&lt;/tt&gt; en el paquete &lt;tt&gt;Bar&lt;/tt&gt; pero &lt;i&gt;fuera de un bloque&lt;/i&gt;, estamos diciendo que (hasta que aparezca otro operador de mbito) debe entenderse que las ocurrencias de &lt;tt&gt;$foo&lt;/tt&gt; se refieren a &lt;tt&gt;$Bar::foo&lt;/tt&gt;. Esto ilustra la diferencia entre &lt;tt&gt;use vars&lt;/tt&gt; y el nuevo &lt;tt&gt;our&lt;/tt&gt;:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perl -wuse strict;our ($bob);use vars qw($carol);$carol = &quot;ted&quot;;$bob = &quot;alice&quot;;print &quot;Bob =&gt; $bob, Carol =&gt; $carol\n&quot;;package Movie;print &quot;Bob =&gt; $bob, Carol =&gt; $carol\n&quot;;&lt;/pre&gt;&lt;p&gt;El segundo &lt;tt&gt;print&lt;/tt&gt; produce un error, porque &lt;tt&gt;$carol&lt;/tt&gt; se toma como &lt;tt&gt;$Movie::carol&lt;/tt&gt;, mientras que &lt;tt&gt;$bob&lt;/tt&gt; es &lt;tt&gt;$main::bob&lt;/tt&gt;.&lt;/p&gt;&lt;p&gt;Mientras que esta &quot;expansin sobre paquetes&quot; (que slo se muestra en el caso de &lt;tt&gt;our&lt;/tt&gt;) es una similaridad funcional entre los dos tipos distintos de operadores de mbito, no debemos olvidar la diferencia entre ellos, que es que &lt;tt&gt;our&lt;/tt&gt; declara una global, pero &lt;tt&gt;my&lt;/tt&gt; no.&lt;/p&gt;&lt;h2&gt;&lt;tt&gt;local&lt;/tt&gt; &lt;i&gt;a.k.a.&lt;/i&gt; mbito dinmico&lt;/h2&gt;&lt;p&gt;Ahora llegamos a &lt;tt&gt;local&lt;/tt&gt;, que es como &lt;tt&gt;my&lt;/tt&gt;, pero debido a su nombre, su funcin se confunde con frecuencia con la de &lt;tt&gt;my&lt;/tt&gt;. Aqu est el detalle: &lt;tt&gt;local $foo&lt;/tt&gt; &lt;i&gt;almacena&lt;/i&gt; el valor actual de la variable &lt;b&gt;global&lt;/b&gt; &lt;tt&gt;$foo&lt;/tt&gt;, y hace que en el bloque actual y en el cdigo al que se llame desde el bloque actual, &lt;tt&gt;$foo&lt;/tt&gt; se refiera al valor que le demos en tal bloque (hacer &lt;tt&gt;local $foo&lt;/tt&gt; le dar a &lt;tt&gt;$foo&lt;/tt&gt; el valor &lt;tt&gt;undef&lt;/tt&gt;, lo mismo que con &lt;tt&gt;my&lt;/tt&gt;). Actualmente, &lt;tt&gt;local&lt;/tt&gt; slo funciona en &lt;b&gt;globales&lt;/b&gt;, no se puede usar sobre una variable &lt;tt&gt;my&lt;/tt&gt;.&lt;/p&gt;&lt;p&gt;Ya que &lt;tt&gt;local&lt;/tt&gt; puede afectar a cosas que ocurren fuera del bloque en que lo hemos usado, &lt;tt&gt;local&lt;/tt&gt; proporciona mbito denominado &lt;i&gt;dinmico&lt;/i&gt;, ya que su efecto se determina a partir de lo que ocurre cuando se ejecuta el programa. Esto es, el compilador no puede saber cuando &lt;tt&gt;local&lt;/tt&gt; har efecto o no durante la compilacin del programa (que ocurre antes de la ejecucin del mismo). Esto distingue el mbito dinmico del lxico proporcionado por &lt;tt&gt;my&lt;/tt&gt; y &lt;tt&gt;our&lt;/tt&gt;, que tienen efectos visibles en tiempo de compilacin.&lt;/p&gt;&lt;p&gt;El resultado bsico de esta diferencia es que si &lt;tt&gt;local&lt;/tt&gt;izamos una variable dentro de un bloque y llamamos a una subrutina desde ese bloque, la subrutina ver el valor de la variable &lt;tt&gt;local&lt;/tt&gt;izada. Esta es una diferencia importante entre &lt;tt&gt;my&lt;/tt&gt; y &lt;tt&gt;local&lt;/tt&gt;. Comparar el ejemplo anterior con este:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perl -wuse strict;use vars qw ($foo); # &quot;our $foo&quot; si usamos 5.6$foo = &quot;global value&quot;;print &quot;\$foo: $foo\n&quot;; # muestra &quot;global value&quot;print &quot;mysub    result &#39;&quot;, &amp;mysub(),    &quot;&#39;\n&quot;; # &quot;global value&quot;print &quot;localsub result &#39;&quot;, &amp;localsub(), &quot;&#39;\n&quot;; # &quot;local value&quot;print &quot;no sub   result &#39;&quot;, &amp;showfoo(),  &quot;&#39;\n&quot;; # &quot;global value&quot;sub mysub { my $foo = &quot;my value&quot;; showfoo();}sub localsub { local $foo = &quot;local value&quot;; showfoo(); # SIEMPRE muestra &quot;local value&quot;}sub showfoo {  return $foo;}__OUTPUT__$foo: global valuemysub    result &#39;global value&#39;localsub result &#39;local value&#39;no sub   result &#39;global value&#39;&lt;/pre&gt;&lt;p&gt;Ntese que &lt;tt&gt;showfoo&lt;/tt&gt; ignora (en apariencia) la declaracin &lt;tt&gt;my&lt;/tt&gt; de &lt;tt&gt;mysub&lt;/tt&gt; (ya que hemos abandonado el bloque en el que la declaracin &lt;tt&gt;my&lt;/tt&gt; tiene efecto) pero la declaracin &lt;tt&gt;local&lt;/tt&gt; de &lt;tt&gt;localsub&lt;/tt&gt; no se ignora. Y despus de abandonar ese bloque, el valor original de &lt;tt&gt;$foo&lt;/tt&gt; se vuelve a ver.&lt;/p&gt;&lt;p&gt;Espero que hayis aprendido tanto al leer esto como yo al escribirlo!&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>POD en 5 minutos (Hue-Bond)</title>
    <link>http://prlmnks.org/html/558831.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/558831.html</guid>

    <description>
        &lt;p&gt;&lt;small&gt;Translated to spanish from [node://Juerd]&#39;s original [id://252477].&lt;/small&gt;&lt;/p&gt;&lt;h1&gt;Plain Old Documentation en 5 minutos&lt;/h1&gt;&lt;h2&gt;La documentacin es importante&lt;/h2&gt;&lt;p&gt;Todos el mundo lo sabe, y sabe por qu. Me voy a saltar esta seccin porque cualquier discusin detallada de por qu la documentacin es importante rompera mi promesa de que se puede aprender a documentar en cinco minutos.&lt;/p&gt;&lt;h2&gt;Documentacin en Perl&lt;/h2&gt;&lt;p&gt;El cdigo fuente en Perl puede contener documentacin en formato POD. POD significa &quot;Plain Old Documentation&quot; (documentacin sencilla y antigua). Se puede mezclar POD con cdigo, poner todo el POD al principio o ponerlo al final. Slo depende del gusto de cada uno. T eliges.&lt;/p&gt;&lt;h2&gt;Encabezados en POD&lt;/h2&gt;&lt;p&gt;La estructura lgica es importante, por tanto se suelen usar encabezados. Hay cuatro niveles, y con esto debera llegar. Se usan los comandos &lt;tt&gt;=head1&lt;/tt&gt; .. &lt;tt&gt;=head4&lt;/tt&gt; (oficialmente se les llama &lt;i&gt;comandos de prrafo&lt;/i&gt;. Son prrafos porque estn separados del resto del POD mediante lneas enblanco).&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;=head1 NOMBREMy::Module - Un mdulo de ejemplo&lt;/pre&gt;&lt;h2&gt;Secciones habituales&lt;/h2&gt;&lt;p&gt;Para mantener las cosas claras, se usan las mismas secciones en todas partes. Ya hemos visto la seccin NOMBRE. S, es costumbre escribir los prrafos head1 en MAYSCULAS. Si haces mdulos para CPAN, debes usar este estilo. Si no, o si usas POD para otras cosas que documentacin (tambin es un formato bueno para escribir artculos o informes), queda a tu eleccin.&lt;/p&gt;&lt;ul&gt;  &lt;li&gt;&lt;i&gt;NOMBRE&lt;/i&gt; contiene el nombre del mdulo o script, un guin y una descripcin corta.&lt;/li&gt;  &lt;li&gt;&lt;i&gt;SINOPSIS&lt;/i&gt; significa &quot;ver todo junto&quot; y muestra ejemplos de uso.&lt;/li&gt;  &lt;li&gt;&lt;i&gt;DESCRIPCIN&lt;/i&gt; contiene una descripcin larga de lo que hace el mdulo y lista sus funciones.&lt;/li&gt;  &lt;li&gt;&lt;i&gt;BUGS&lt;/i&gt; o &lt;i&gt;ADVERTENCIAS&lt;/i&gt; habla de los bugs o problemas que el usuario debera conocer.&lt;/li&gt;  &lt;li&gt;&lt;i&gt;AGRADECIMIENTOS&lt;/i&gt; es donde el autor agracede a los que arreglan bugs y prueban el programa.&lt;/li&gt;  &lt;li&gt;&lt;i&gt;COPYRIGHT&lt;/i&gt; o &lt;i&gt;LICENCIA&lt;/i&gt; menciona las restricciones de copyright. Sin embargo, no hay que poner toda la GPL :).&lt;/li&gt;  &lt;li&gt;&lt;i&gt;DISPONIBILIDAD&lt;/i&gt; anuncia dnde se pueden encontrar versiones ms recientes.&lt;/li&gt;  &lt;li&gt;&lt;i&gt;AUTOR&lt;/i&gt; explica quin ha hecho el programa, si no lo hace ya la seccin COPYRIGHT.&lt;/li&gt;  &lt;li&gt;&lt;i&gt;VASE TAMBIN&lt;/i&gt; refiere al lector a un lugar con ms documentacin.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Todos estos son para &lt;tt&gt;=head1&lt;/tt&gt;.&lt;/p&gt;&lt;p&gt;Las funciones, mtodos y todo eso se explican normalmente en una seccin &lt;tt&gt;=head2&lt;/tt&gt; bajo DESCRIPCIN.&lt;/p&gt;&lt;p&gt;Como mnimo, hay que documentar los argumentos que reciben las funciones y los valores que se devuelven. Si hay condiciones necesarias para algo, se deben mencionar. Si una funcin devuelve &lt;tt&gt;undef&lt;/tt&gt; cuando hay errores, hay que hacrselo saber a la gente.&lt;/p&gt;&lt;p&gt;Est bien escribir frases cortas. Es mejor evitar las largas.&lt;/p&gt;&lt;h2&gt;Ejemplos de cdigo&lt;/h2&gt;&lt;p&gt;Los prrafos tabulados se toman como cdigo, con la tabulacin intacta. As de fcil!:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;=head1 SINOPSIS    use My::Module;    my $object = My::Module-&gt;new();     print $object-&gt;as_string;&lt;/pre&gt;&lt;p&gt;Esto se llama un &lt;i&gt;prrafo textual&lt;/i&gt;.&lt;/p&gt;&lt;h2&gt;Marcado&lt;/h2&gt;&lt;p&gt;POD soporta un pequeo conjunto de elementos de marcado. Para mantener mi promesa, me voy a limitar a enumerarlos:&lt;/p&gt;&lt;ul&gt;  &lt;li&gt;&lt;tt&gt;B&amp;lt;texto en negrita&amp;gt;&lt;/tt&gt;&lt;/li&gt;  &lt;li&gt;&lt;tt&gt;B&amp;lt;texto en cursiva&amp;gt;&lt;/tt&gt;&lt;/li&gt;  &lt;li&gt;&lt;tt&gt;B&amp;lt;texto subrayado&amp;gt;&lt;/tt&gt;&lt;/li&gt;  &lt;li&gt;&lt;tt&gt;B&amp;lt;cdigo&amp;gt;&lt;/tt&gt;&lt;/li&gt;  &lt;li&gt;&lt;tt&gt;B&amp;lt;y se pueden I&amp;lt;anidar&amp;gt;&amp;gt;&lt;/tt&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Tambin hay F, S, X y Z pero apenas se usan y no merece la pena explicarlos en un tutorial pequeo como este.&lt;/p&gt;&lt;p&gt;Si alguna vez hace falta incluir un carcter &#39;&amp;gt;&#39; dentro de cdigo, hay dos opciones. Si queremos poner &lt;tt&gt;$foo-&gt;bar&lt;/tt&gt; con fuente de cdigo, podemos hacer esto:&lt;/p&gt;&lt;ul&gt;  &lt;li&gt;&lt;tt&gt;C&amp;lt;$foo-E&amp;lt;gt&amp;gt;bar&amp;gt;&lt;/tt&gt;&lt;/li&gt;  &lt;li&gt;&lt;tt&gt;C&amp;lt;&amp;lt; $foo-&amp;gt;bar &amp;gt;&amp;gt;&lt;/tt&gt; (los espacios son necesarios!)&lt;/li&gt;  &lt;li&gt;&lt;tt&gt;C&amp;lt;&amp;lt;&amp;lt; $foo-&amp;gt;bar &amp;gt;&amp;gt;&amp;gt;&lt;/tt&gt; (los espacios son necesarios!)&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Entidades&lt;/h2&gt;&lt;p&gt;Hemos visto que se puede usar E para entidades. Son como las entidades de HTML; tambin tenemos estas:&lt;/p&gt;&lt;ul&gt;  &lt;li&gt;&lt;tt&gt;verbar&lt;/tt&gt; para una barra vertical.&lt;/li&gt;  &lt;li&gt;&lt;tt&gt;sol&lt;/tt&gt; para una barra (solidus).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Las entidades numricas pueden ir en decimal, octal (con el prefijo &#39;0&#39;) y en hexadecimal (con el prefijo &#39;0x&#39;).&lt;/p&gt;&lt;h2&gt;Listas&lt;/h2&gt;&lt;p&gt;En este caso un ejemplo es mucho ms claro que una explicacin:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;=head2 Mtodos=over 12=item C&lt;new&gt;Devuelve un objeto My::Module nuevo.=item C&lt;as_string&gt;Devuelve una representacin delobjeto en forma de cadena. Sirveprincipalmente para depuracin.=back&lt;/pre&gt;&lt;p&gt;Como puede verse, se empieza esta lista con &lt;tt&gt;=over&lt;/tt&gt; y la acabamos con &lt;tt&gt;=back&lt;/tt&gt;. Entre ambos comandos hay &lt;tt&gt;=item&lt;/tt&gt;s. El nmero despus de &lt;tt&gt;=over&lt;/tt&gt; es el nivel de tabulacin, usado principalmente por los renderizadores de texto para conseguir un diseo horizontal. pod2text convierte el ejemplo anterior en:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;  Methods      &quot;new&quot;       Returns a new                  My::Module object.      &quot;as_string&quot; Returns a stringified                   representation of the                   object. This is mainly                  for debugging purposes.&lt;/pre&gt;&lt;h2&gt;Otras cositas de POD&lt;/h2&gt;&lt;p&gt;Se puede usar L para enlazar a secciones del mismo documento o a otros documentos. POD se termina con &lt;tt&gt;=cut&lt;/tt&gt; para volver a Perl. Hay comandos especiales para los distintos formatos de salida. Para leer la documentacin completa de POD, teclear:&lt;/p&gt;&lt;tt class=&quot;inline_code&quot;&gt;perldoc perlpod&lt;/tt&gt;&lt;h2&gt;Un ejemplo completo&lt;/h2&gt;&lt;pre class=&quot;block_code&quot;&gt;=head1 NOMBREMy::Module - Un mdulo de ejemplo=head1 SINOPSIS    use My::Module;    my $object = My::Module-&gt;new();    print $object-&gt;as_string;=head1 DESCRIPCINEste mdulo no existe en realidad, sehizo con el nico objetivo de mostrarcmo funciona POD.=head2 Mtodos=over 12=item C&lt;new&gt;Devuelve un objeto My::Module nuevo.=item C&lt;as_string&gt;Devuelve una representacin delobjeto en forma de cadena. Sirveprincipalmente para depuracin.=back=head1 AUTORJuerd - &lt;http://juerd.nl/&gt;=head1 VASE TAMBINL&lt;perlpod&gt;, L&lt;perlpodspec&gt;=cut&lt;/pre&gt;&lt;h2&gt;Conclusin&lt;/h2&gt;&lt;p&gt;Documentar con POD es fcil. A divertirse!&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>perlunitut: Unicode in Perl (Juerd)</title>
    <link>http://prlmnks.org/html/551676.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/551676.html</guid>

    <description>
        &lt;p&gt;&lt;a name=&quot;__index__&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;!-- INDEX BEGIN --&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#name&quot;&gt;NAME&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#description&quot;&gt;DESCRIPTION&lt;/a&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#definitions&quot;&gt;Definitions&lt;/a&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#unicode&quot;&gt;Unicode&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#utf8&quot;&gt;UTF-8&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#text_strings__character_strings_&quot;&gt;Text strings (character strings)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#binary_strings__byte_strings_&quot;&gt;Binary strings (byte strings)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#encoding&quot;&gt;Encoding&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#decoding&quot;&gt;Decoding&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#internal_format&quot;&gt;Internal format&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;a href=&quot;#your_new_toolkit&quot;&gt;Your new toolkit&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#i_o_flow__the_actual_5_minute_tutorial_&quot;&gt;I/O flow (the actual 5 minute tutorial)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#q_and_a&quot;&gt;Q and A&lt;/a&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#this_isn_t_really_a_unicode_tutorial__is_it&quot;&gt;This isn&#39;t really a Unicode tutorial, is it?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#what_about_binary_data__like_images&quot;&gt;What about binary data, like images?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#what_about_the_utf8_flag&quot;&gt;What about the UTF-8 flag?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#when_should_i_decode_or_encode&quot;&gt;When should I decode or encode?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#what_if_i_don_t_decode&quot;&gt;What if I don&#39;t decode?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#what_if_i_don_t_encode&quot;&gt;What if I don&#39;t encode?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#is_there_a_way_to_automatically_decode_or_encode&quot;&gt;Is there a way to automatically decode or encode?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#cheat__tell_me__how_can_i_cheat&quot;&gt;Cheat?! Tell me, how can I cheat?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#what_if_i_don_t_know_which_encoding_was_used&quot;&gt;What if I don&#39;t know which encoding was used?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#can_i_use_unicode_in_my_perl_sources&quot;&gt;Can I use Unicode in my Perl sources?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#data__dumper_doesn_t_restore_the_utf8_flag__is_it_broken&quot;&gt;Data::Dumper doesn&#39;t restore the UTF-8 flag; is it broken?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#how_can_i_determine_if_a_string_is_a_text_string_or_a_binary_string&quot;&gt;How can I determine if a string is a text string or a binary string?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#how_do_i_convert_from_encoding_foo_to_encoding_bar&quot;&gt;How do I convert from encoding FOO to encoding BAR?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#what_about_the_use_bytes_pragma&quot;&gt;What about the &lt;tt class=&quot;inline_code&quot;&gt;use bytes&lt;/tt&gt; pragma?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#what_are_decode_utf8_and_encode_utf8&quot;&gt;What are &lt;tt class=&quot;inline_code&quot;&gt;decode_utf8&lt;/tt&gt; and &lt;tt class=&quot;inline_code&quot;&gt;encode_utf8&lt;/tt&gt;?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#what_s_the_difference_between_utf8_and_utf8&quot;&gt;What&#39;s the difference between &lt;tt class=&quot;inline_code&quot;&gt;UTF-8&lt;/tt&gt; and &lt;tt class=&quot;inline_code&quot;&gt;utf8&lt;/tt&gt;?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#what_character_encodings_does_perl_support&quot;&gt;What character encodings does Perl support?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#which_version_of_perl_should_i_use&quot;&gt;Which version of perl should I use?&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;&lt;a href=&quot;#summary&quot;&gt;SUMMARY&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#acknowledgements&quot;&gt;ACKNOWLEDGEMENTS&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#author&quot;&gt;AUTHOR&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#see_also&quot;&gt;SEE ALSO&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;!-- INDEX END --&gt;&lt;hr /&gt;&lt;p&gt;&lt;/p&gt;&lt;h1&gt;&lt;a name=&quot;name&quot;&gt;NAME&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;perlunitut - Perl Unicode Tutorial&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;hr /&gt;&lt;h1&gt;&lt;a name=&quot;description&quot;&gt;DESCRIPTION&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;The days of just flinging strings around are over. It&#39;s well established thatmodern programs need to be capable of communicating funny accented letters, andthings like euro symbols. This means that programmers need new habits. It&#39;seasy to program Unicode capable software, but it does require discipline to doit right.&lt;/p&gt;&lt;p&gt;There&#39;s a lot to know about character sets, and text encodings. It&#39;s probablybest to spend a full day learning all this, but the basics can be learned inminutes.&lt;/p&gt;&lt;p&gt;These are not the very basics, though. It is assumed that you alreadyknow the difference between bytes and characters, and realise (and accept!)that there are many different character sets and encodings, and that yourprogram has to be explicit about them. Recommended reading is ``The AbsoluteMinimum Every Software Developer Absolutely, Positively Must Know About Unicodeand Character Sets (No Excuses!)&#39;&#39; by Joel Spolsky, at&lt;a href=&quot;http://joelonsoftware.com/articles/Unicode.html&quot;&gt;http://joelonsoftware.com/articles/Unicode.html&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;This tutorial speaks in rather absolute terms, and provides only a limited viewof the wealth of character string related features that Perl has to offer. Formost projects, this information will probably suffice.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h2&gt;&lt;a name=&quot;definitions&quot;&gt;Definitions&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;It&#39;s important to set a few things straight first. This is the most importantpart of this tutorial. This view may conflict with other information that youmay have found on the web, but that&#39;s mostly because many sources are wrong.&lt;/p&gt;&lt;p&gt;You may have to re-read this entire section a few times...&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;unicode&quot;&gt;Unicode&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Unicode&lt;/strong&gt; is a character set with room for lots of characters. The ordinalvalue of a character is called a &lt;strong&gt;code point&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;There are many, many code points, but computers work with bytes, and a byte canhave only 256 values. Unicode has many more characters, so you need a methodto make these accessible.&lt;/p&gt;&lt;p&gt;Unicode is encoded using several competing encodings, of which UTF-8 is themost used. In a Unicode encoding, multiple subsequent bytes can be used tostore a single code point, or simply: character.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;utf8&quot;&gt;UTF-8&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;UTF-8&lt;/strong&gt; is a Unicode encoding. Many people think that Unicode and UTF-8 arethe same thing, but they&#39;re not. There are more Unicode encodings, but much ofthe world has standardized on UTF-8.&lt;/p&gt;&lt;p&gt;UTF-8 treats the first 128 codepoints, 0..127, the same as ASCII. They takeonly one byte per character. All other characters are encoded as two or more(up to six) bytes using a complex scheme. Fortunately, Perl handles this forus, so we don&#39;t have to worry about this.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;text_strings__character_strings_&quot;&gt;Text strings (character strings)&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Text strings&lt;/strong&gt;, or &lt;strong&gt;character strings&lt;/strong&gt; are made of characters. Bytes areirrelevant here, and so are encodings. Each character is just that: thecharacter.&lt;/p&gt;&lt;p&gt;On a text string, you would do things like:&lt;/p&gt;&lt;pre&gt;    $text =~ s/foo/bar/;    if ($string =~ /^\d+$/) { ... }    $text = ucfirst $text;    my $character_count = length $text;&lt;/pre&gt;&lt;p&gt;The value of a character (&lt;tt class=&quot;inline_code&quot;&gt;ord&lt;/tt&gt;, &lt;tt class=&quot;inline_code&quot;&gt;chr&lt;/tt&gt;) is the corresponding Unicode codepoint.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;binary_strings__byte_strings_&quot;&gt;Binary strings (byte strings)&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Binary strings&lt;/strong&gt;, or &lt;strong&gt;byte strings&lt;/strong&gt; are made of bytes. Here, you don&#39;t havecharacters, just bytes. All communication with the outside world (anythingoutside of your current Perl process) is done in binary.&lt;/p&gt;&lt;p&gt;On a binary string, you would do things like:&lt;/p&gt;&lt;pre&gt;    my (@length_content) = unpack &amp;quot;(V/a)*&amp;quot;, $binary;    $binary =~ s/\x00\x0F/\xFF\xF0/;  # for the brave :)    print {$fh} $binary;    my $byte_count = length $binary;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;encoding&quot;&gt;Encoding&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Encoding&lt;/strong&gt; (as a verb) is the conversion from &lt;em&gt;text&lt;/em&gt; to &lt;em&gt;binary&lt;/em&gt;. To encode,you have to supply the target encoding, for example &lt;tt class=&quot;inline_code&quot;&gt;iso-8859-1&lt;/tt&gt; or &lt;tt class=&quot;inline_code&quot;&gt;UTF-8&lt;/tt&gt;.Some encodings, like the &lt;tt class=&quot;inline_code&quot;&gt;iso-8859&lt;/tt&gt; (``latin&#39;&#39;) range, do not support theUnicode standard; characters that can&#39;t be represented are lost in theconversion.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;decoding&quot;&gt;Decoding&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Decoding&lt;/strong&gt; is the conversion from &lt;em&gt;binary&lt;/em&gt; to &lt;em&gt;text&lt;/em&gt;. To decode, you have toknow what encoding was used during the encoding phase. And most of all, it mustbe something decodable. It doesn&#39;t make much sense to decode a PNG image into atext string.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;internal_format&quot;&gt;Internal format&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Perl has an &lt;strong&gt;internal format&lt;/strong&gt;, an encoding that it uses to encode text stringsso it can store them in memory. All text strings are in this internal format.In fact, text strings are never in any other format!&lt;/p&gt;&lt;p&gt;You shouldn&#39;t worry about what this format is, because conversion isautomatically done when you decode or encode.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h2&gt;&lt;a name=&quot;your_new_toolkit&quot;&gt;Your new toolkit&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Add to your standard heading the following line:&lt;/p&gt;&lt;pre&gt;    use Encode qw(encode decode);&lt;/pre&gt;&lt;p&gt;Or, if you&#39;re lazy, just:&lt;/p&gt;&lt;pre&gt;    use Encode;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;h2&gt;&lt;a name=&quot;i_o_flow__the_actual_5_minute_tutorial_&quot;&gt;I/O flow (the actual 5 minute tutorial)&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The typical input/output flow of a program is:&lt;/p&gt;&lt;pre&gt;    1. Receive and decode    2. Process    3. Encode and output&lt;/pre&gt;&lt;p&gt;If your input is binary, and is supposed to remain binary, you shouldn&#39;t decodeit to a text string, of course. But in all other cases, you should decode it.&lt;/p&gt;&lt;p&gt;Decoding can&#39;t happen reliably if you don&#39;t know how the data was encoded. Ifyou get to choose, it&#39;s a good idea to standardize on UTF-8.&lt;/p&gt;&lt;pre&gt;    my $foo   = decode(&#39;UTF-8&#39;, get &#39;&lt;a href=&quot;http://example.com/&quot;&gt;http://example.com/&lt;/a&gt;&#39;);    my $bar   = decode(&#39;ISO-8859-1&#39;, readline STDIN);    my $xyzzy = decode(&#39;Windows-1251&#39;, $cgi-&amp;gt;param(&#39;foo&#39;));&lt;/pre&gt;&lt;p&gt;Processing happens as you knew before. The only difference is that you&#39;re nowusing characters instead of bytes. That&#39;s very useful if you use things like&lt;tt class=&quot;inline_code&quot;&gt;substr&lt;/tt&gt;, or &lt;tt class=&quot;inline_code&quot;&gt;length&lt;/tt&gt;.&lt;/p&gt;&lt;p&gt;It&#39;s important to realize that there are no bytes in a text string. Of course,Perl has its internal encoding to store the string in memory, but ignore that.If you have to do anything with the number of bytes, it&#39;s probably best to movethat part to step 3, just after you&#39;ve encoded the string. Then you knowexactly how many bytes it will be in the destination string.&lt;/p&gt;&lt;p&gt;The syntax for encoding text strings to binary strings is as simple as decoding:&lt;/p&gt;&lt;pre&gt;    $body = encode(&#39;UTF-8&#39;, $body);&lt;/pre&gt;&lt;p&gt;If you needed to know the length of the string in bytes, now&#39;s the perfect timefor that. Because &lt;tt class=&quot;inline_code&quot;&gt;$body&lt;/tt&gt; is now a byte string, &lt;tt class=&quot;inline_code&quot;&gt;length&lt;/tt&gt; will report thenumber of bytes, instead of the number of characters. The number ofcharacters is no longer known, because characters only exist in text strings.&lt;/p&gt;&lt;pre&gt;    my $byte_count = length $body;&lt;/pre&gt;&lt;p&gt;And if the protocol you&#39;re using supports a way of letting the recipient knowwhich character encoding you used, please help the receiving end by using thatfeature! For example, E-mail and HTTP support MIME headers, so you can use the&lt;tt class=&quot;inline_code&quot;&gt;Content-Type&lt;/tt&gt; header. They can also have &lt;tt class=&quot;inline_code&quot;&gt;Content-Length&lt;/tt&gt; to indicate thenumber of &lt;em&gt;bytes&lt;/em&gt;, which is always a good idea to supply if the number isknown.&lt;/p&gt;&lt;pre&gt;    &amp;quot;Content-Type: text/plain; charset=UTF-8&amp;quot;,    &amp;quot;Content-Length: $byte_count&amp;quot;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;h2&gt;&lt;a name=&quot;q_and_a&quot;&gt;Q and A&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;this_isn_t_really_a_unicode_tutorial__is_it&quot;&gt;This isn&#39;t really a Unicode tutorial, is it?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;No, Perl has an abstracted interface for all supported character encodings, sothis is actually a generic &lt;tt class=&quot;inline_code&quot;&gt;Encode&lt;/tt&gt; tutorial. But many people think thatUnicode is special and magical, and I did&#39;t want to disappoint them, so Idecided to call this document a Unicode tutorial.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;what_about_binary_data__like_images&quot;&gt;What about binary data, like images?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Well, apart from a bare &lt;tt class=&quot;inline_code&quot;&gt;binmode $fh&lt;/tt&gt;, you shouldn&#39;t treat them specially.(The binmode is needed because otherwise Perl may convert line endings on Win32systems.)&lt;/p&gt;&lt;p&gt;Be careful, though, to never combine text strings with binary strings. If youneed text in a binary stream, encode your text strings first using theappropriate encoding, then join them with binary strings. See also: ``What if Idon&#39;t encode?&#39;&#39;.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;what_about_the_utf8_flag&quot;&gt;What about the UTF-8 flag?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Please, unless you&#39;re hacking the internals, or debugging weirdness, don&#39;tthink about the UTF-8 flag at all. That means that you very probably shouldn&#39;tuse &lt;tt class=&quot;inline_code&quot;&gt;is_utf8&lt;/tt&gt;, &lt;tt class=&quot;inline_code&quot;&gt;_utf8_on&lt;/tt&gt; or &lt;tt class=&quot;inline_code&quot;&gt;_utf8_off&lt;/tt&gt; at all.&lt;/p&gt;&lt;p&gt;Perl&#39;s internal format happens to be UTF-8. Unfortunately, Perl can&#39;t keep asecret, so everyone knows about this.  That is the source of much confusion.It&#39;s better to pretend that the internal format is some unknown encoding,and that you always have to encode and decode explicitly.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;when_should_i_decode_or_encode&quot;&gt;When should I decode or encode?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Whenever you&#39;re communicating with anything that is external to your perlprocess, like a database, a text file, a socket, or another program. Even ifthe thing you&#39;re communicating with is also written in Perl.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;what_if_i_don_t_decode&quot;&gt;What if I don&#39;t decode?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Whenever your encoded, binary string is used together with a text string, Perlwill assume that your binary string was encoded with ISO-8859-1, also known aslatin-1. If it wasn&#39;t latin-1, then your data is unpleasantly converted. Forexample, if it was UTF-8, the individual bytes of multibyte characters are seenas separate characters, and then again converted to UTF-8. Such double encodingcan be compared to double HTML encoding (&lt;tt class=&quot;inline_code&quot;&gt;&amp;amp;amp;gt;&lt;/tt&gt;), or double URI encoding(&lt;tt class=&quot;inline_code&quot;&gt;%253E&lt;/tt&gt;).&lt;/p&gt;&lt;p&gt;This silent implicit decoding is known as ``upgrading&#39;&#39;. That may soundpositive, but it&#39;s best to avoid it.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;what_if_i_don_t_encode&quot;&gt;What if I don&#39;t encode?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Your text string will be sent using the bytes in Perl&#39;s internal format. Insome cases, Perl will warn you that you&#39;re doing something wrong, with afriendly warning:&lt;/p&gt;&lt;pre&gt;    Wide character in print at example.pl line 2.&lt;/pre&gt;&lt;p&gt;Because the internal format is really UTF-8, these bugs are hard to spot,because UTF-8 is usually the encoding you wanted! But don&#39;t be lazy, and don&#39;tuse the fact that Perl&#39;s internal format is UTF-8 to your advantage. Encodeexplicitly to avoid weird bugs, and to show to maintenance programmers that youthought this through.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;is_there_a_way_to_automatically_decode_or_encode&quot;&gt;Is there a way to automatically decode or encode?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;If all data that comes from a certain handle is encoded in exactly the sameway, you can tell the PerlIO system to automatically decode everything, withthe &lt;tt class=&quot;inline_code&quot;&gt;encoding&lt;/tt&gt; layer.&lt;/p&gt;&lt;p&gt;You can provide this layer when &lt;tt class=&quot;inline_code&quot;&gt;open&lt;/tt&gt;ing the file:&lt;/p&gt;&lt;pre&gt;    open my $fh, &#39;&amp;gt;:encoding(UTF-8)&#39;, $filename;  # auto encoding on write    open my $fh, &#39;&amp;lt;:encoding(UTF-8)&#39;, $filename;  # auto decoding on read&lt;/pre&gt;&lt;p&gt;Or if you already have an open filehandle:&lt;/p&gt;&lt;pre&gt;    binmode $fh, &#39;:encoding(UTF-8)&#39;;&lt;/pre&gt;&lt;p&gt;Some database drivers for DBI can also automatically encode and decode, butthat is typically limited to the UTF-8 encoding, because they cheat.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;cheat__tell_me__how_can_i_cheat&quot;&gt;Cheat?! Tell me, how can I cheat?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Well, because Perl&#39;s internal format is UTF-8, you can just skip the encodingor decoding step, and manipulate the UTF-8 flag directly.&lt;/p&gt;&lt;p&gt;Instead of &lt;tt class=&quot;inline_code&quot;&gt;:encoding(UTF-8)&lt;/tt&gt;, you can simply use &lt;tt class=&quot;inline_code&quot;&gt;:utf8&lt;/tt&gt;. This is widelyaccepted as good behavior.&lt;/p&gt;&lt;p&gt;Instead of &lt;tt class=&quot;inline_code&quot;&gt;decode&lt;/tt&gt; and &lt;tt class=&quot;inline_code&quot;&gt;encode&lt;/tt&gt;, you could use &lt;tt class=&quot;inline_code&quot;&gt;_utf8_on&lt;/tt&gt; and &lt;tt class=&quot;inline_code&quot;&gt;_utf8_off&lt;/tt&gt;.But this is, contrary to &lt;tt class=&quot;inline_code&quot;&gt;:utf8&lt;/tt&gt;, considered bad style.&lt;/p&gt;&lt;p&gt;There are some shortcuts for oneliners; see &lt;tt class=&quot;inline_code&quot;&gt;-C&lt;/tt&gt; in &lt;em&gt;perlrun&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;what_if_i_don_t_know_which_encoding_was_used&quot;&gt;What if I don&#39;t know which encoding was used?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Do whatever you can to find out, and if you have to: guess. (Don&#39;t forget todocument your guess with a comment.)&lt;/p&gt;&lt;p&gt;You could open the document in a web browser, and change the character set orcharacter encoding until you can visually confirm that all characters look theway they should.&lt;/p&gt;&lt;p&gt;There is no way to reliably detect the encoding automatically, so if peoplekeep sending you data without charset indication, you may have to educate them.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;can_i_use_unicode_in_my_perl_sources&quot;&gt;Can I use Unicode in my Perl sources?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Yes, you can! If your sources are UTF-8 encoded, you can indicate that with the&lt;tt class=&quot;inline_code&quot;&gt;use utf8&lt;/tt&gt; pragma.&lt;/p&gt;&lt;pre&gt;    use utf8;&lt;/pre&gt;&lt;p&gt;This doesn&#39;t do anything to your input, or to your output. It only influencesthe way your sources are read. You can use Unicode in string literals, inidentifiers (but they still have to be ``word characters&#39;&#39; according to &lt;tt class=&quot;inline_code&quot;&gt;\w&lt;/tt&gt;),and even in custom delimiters.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;data__dumper_doesn_t_restore_the_utf8_flag__is_it_broken&quot;&gt;Data::Dumper doesn&#39;t restore the UTF-8 flag; is it broken?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;No, Data::Dumper&#39;s Unicode abilities are as they should be. There have beensome complaints that it should restore the UTF-8 flag when the data is readagain with &lt;tt class=&quot;inline_code&quot;&gt;eval&lt;/tt&gt;. However, you should really not look at the flag, andnothing indicates that Data::Dumper should break this rule.&lt;/p&gt;&lt;p&gt;Here&#39;s what happens: when Perl reads in a string literal, it sticks to 8 bitencoding as long as it can. (But perhaps originally it was internally encodedas UTF-8, when you dumped it.) When it has to give that up because othercharacters are added to the text string, it silently upgrades the string toUTF-8.&lt;/p&gt;&lt;p&gt;If you properly encode your strings for output, none of this is of yourconcern, and you can just &lt;tt class=&quot;inline_code&quot;&gt;eval&lt;/tt&gt; dumped data as always.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;how_can_i_determine_if_a_string_is_a_text_string_or_a_binary_string&quot;&gt;How can I determine if a string is a text string or a binary string?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;You can&#39;t. Some use the UTF-8 flag for this, but that&#39;s misuse, and makes wellbehaved modules like Data::Dumper look bad. The flag is useless for thispurpose, because it&#39;s off when an 8 bit encoding (by default ISO-8859-1) isused to store the string.&lt;/p&gt;&lt;p&gt;This is something you, the programmer, has to keep track of; sorry. You couldconsider adopting a kind of ``Hungarian notation&#39;&#39; to help with this.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;how_do_i_convert_from_encoding_foo_to_encoding_bar&quot;&gt;How do I convert from encoding FOO to encoding BAR?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;By first converting the FOO-encoded byte string to a text string, and then thetext string to a BAR-encoded byte string:&lt;/p&gt;&lt;pre&gt;    my $text_string = decode(&#39;FOO&#39;, $foo_string);    my $bar_string  = encode(&#39;BAR&#39;, $text_string);&lt;/pre&gt;&lt;p&gt;or by skipping the text string part, and going directly from one binaryencoding to the other:&lt;/p&gt;&lt;pre&gt;    use Encode qw(from_to);    from_to($string, &#39;FOO&#39;, &#39;BAR&#39;);  # changes contents of $string&lt;/pre&gt;&lt;p&gt;or by letting automatic decoding and encoding do all the work:&lt;/p&gt;&lt;pre&gt;    open my $foofh, &#39;&amp;lt;:encoding(FOO)&#39;, &#39;example.foo.txt&#39;;    open my $barfh, &#39;&amp;gt;:encoding(BAR)&#39;, &#39;example.bar.txt&#39;;    print { $barfh } $_ while &amp;lt;$foofh&amp;gt;;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;what_about_the_use_bytes_pragma&quot;&gt;What about the &lt;tt class=&quot;inline_code&quot;&gt;use bytes&lt;/tt&gt; pragma?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Don&#39;t use it. It makes no sense to deal with bytes in a text string, and itmakes no sense to deal with characters in a byte string. Do the properconversions (by decoding/encoding), and things will work out well: you getcharacter counts for decoded data, and byte counts for encoded data.&lt;/p&gt;&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;use bytes&lt;/tt&gt; is usually a failed attempt to do something useful. Just forgetabout it.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;what_are_decode_utf8_and_encode_utf8&quot;&gt;What are &lt;tt class=&quot;inline_code&quot;&gt;decode_utf8&lt;/tt&gt; and &lt;tt class=&quot;inline_code&quot;&gt;encode_utf8&lt;/tt&gt;?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;These are alternate syntaxes for &lt;tt class=&quot;inline_code&quot;&gt;decode(&#39;utf8&#39;, ...)&lt;/tt&gt; and &lt;pre class=&quot;block_code&quot;&gt;encode(&#39;utf8&#39;,...)&lt;/pre&gt;.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;what_s_the_difference_between_utf8_and_utf8&quot;&gt;What&#39;s the difference between &lt;tt class=&quot;inline_code&quot;&gt;UTF-8&lt;/tt&gt; and &lt;tt class=&quot;inline_code&quot;&gt;utf8&lt;/tt&gt;?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;UTF-8&lt;/tt&gt; is the official standard. &lt;tt class=&quot;inline_code&quot;&gt;utf8&lt;/tt&gt; is Perl&#39;s way of being liberal inwhat it accepts. If you have to communicate with things that aren&#39;t so liberal,you may want to consider using &lt;tt class=&quot;inline_code&quot;&gt;UTF-8&lt;/tt&gt;. If you have to communicate with thingsthat are too liberal, you may have to use &lt;tt class=&quot;inline_code&quot;&gt;utf8&lt;/tt&gt;. The full explanation is in&lt;em&gt;Encode&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;UTF-8&lt;/tt&gt; is internally known as &lt;tt class=&quot;inline_code&quot;&gt;utf-8-strict&lt;/tt&gt;. This tutorial uses UTF-8consistently, even where utf8 is actually used internally, because thedistinction can be hard to make, and is mostly irrelevant.&lt;/p&gt;&lt;p&gt;Okay, if you insist: the ``internal format&#39;&#39; is utf8, not UTF-8.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;what_character_encodings_does_perl_support&quot;&gt;What character encodings does Perl support?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;To find out which character encodings your Perl supports, run:&lt;/p&gt;&lt;pre&gt;    perl -MEncode -le &amp;quot;print for Encode-&amp;gt;encodings( q&lt;a href=&quot;/out/node/:all&quot;&gt;:all&lt;/a&gt; )&amp;quot;;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;which_version_of_perl_should_i_use&quot;&gt;Which version of perl should I use?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Well, if you can, upgrade to the most recent, but certainly &lt;tt class=&quot;inline_code&quot;&gt;5.8.1&lt;/tt&gt; or newer.This tutorial is based on the status quo as of &lt;tt class=&quot;inline_code&quot;&gt;5.8.7&lt;/tt&gt;.&lt;/p&gt;&lt;p&gt;You should also check your modules, and upgrade them if necessary. For example,HTML::Entities requires version &amp;gt;= 1.32 to function correctly, even though thechangelog is silent about this.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;hr /&gt;&lt;h1&gt;&lt;a name=&quot;summary&quot;&gt;SUMMARY&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Decode everything you receive, encode everything you send out. (If it&#39;s textdata.)&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;hr /&gt;&lt;h1&gt;&lt;a name=&quot;acknowledgements&quot;&gt;ACKNOWLEDGEMENTS&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Thanks to Johan Vromans from Squirrel Consultancy. His UTF-8 rants during theAmsterdam Perl Mongers meetings got me interested and determined to find outhow to use character encodings in Perl in ways that don&#39;t break easily.&lt;/p&gt;&lt;p&gt;Thanks to Gerard Goossen from TTY. His presentation ``UTF-8 in the wild&#39;&#39; (DutchPerl Workshop 2006) inspired me to publish my thoughts and write this tutorial.&lt;/p&gt;&lt;p&gt;Thanks to the people who asked about this kind of stuff in several Perl IRCchannels, and have constantly reminded me that a simpler explanation wasneeded.&lt;/p&gt;&lt;p&gt;Thanks to the people who reviewed this document for me, before it went public.They are: Benjamin Smith, Jan-Pieter Cornet, Johan Vromans, Lukas Mai, NathanGray.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;hr /&gt;&lt;h1&gt;&lt;a name=&quot;author&quot;&gt;AUTHOR&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Juerd Waalboer &amp;lt;&lt;a href=&quot;mailto:juerd@cpan.org&quot;&gt;juerd@cpan.org&lt;/a&gt;&amp;gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;hr /&gt;&lt;h1&gt;&lt;a name=&quot;see_also&quot;&gt;SEE ALSO&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;&lt;em&gt;perlunicode&lt;/em&gt;, &lt;em&gt;perluniintro&lt;/em&gt;, &lt;em&gt;Encode&lt;/em&gt;&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>A Simple Socket Server Using &#39;inetd&#39; (dwildesnl)</title>
    <link>http://prlmnks.org/html/544341.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/544341.html</guid>

    <description>
        &lt;B&gt;Using &lt;tt class=&quot;inline_code&quot;&gt;inetd&lt;/tt&gt; to serve a socket&lt;/b&gt;&lt;BR&gt;&lt;BR&gt;It is often the case that one needs to test a system before the hardware is available or on-line. In my case, I&#39;m developing an interface which will talk to a socket on a complex piece of Fab Metrology gear called an Applied Materials NanoSEM, using a complex protocol called SEMI SECS-II/GEM HSMS. I needed a quick and dirty handler to act as the NanoSEM while I get the protocol parser working.&lt;BR&gt;&lt;BR&gt;UNIX-like systems such as FreeBSD and Linux have a nifty feature called &lt;tt class=&quot;inline_code&quot;&gt;inetd&lt;/tt&gt;, which comes to our rescue. &lt;tt class=&quot;inline_code&quot;&gt;inetd&lt;/tt&gt; runs a program you specify whenever somebody else tries to connect to the socket you&#39;ve chosen. By making a few simple configuration improvements, we can send our input to the specified socket, and inetd invokes our program, passing our input to it as STDIN. Our handler then processes it and spits out its response as STDOUT back to our socket. Cool, huh? What&#39;s even more cool is that if another process (or system) also tries to connect to the same socket, &lt;tt class=&quot;inline_code&quot;&gt;inetd&lt;/tt&gt; will invoke another copy of our handler without bothering the first one.&lt;BR&gt;&lt;BR&gt;&lt;READMORE&gt;Interested? Okay, here&#39;s the code...&lt;BR&gt;&lt;BR&gt;&lt;B&gt;The  server handler:&lt;/b&gt;&lt;BR&gt;&lt;BR&gt;&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perl -w -T# sinet.pl A simple inetd socket server.use strict;my $old_fh = select(STDOUT);$| = 1;select($old_fh);while( my $line = &lt;STDIN&gt; ){    $line =~ s/\r?\n$//;    if ($line =~ /endit/)     {die &quot;shutting down\n&quot;;    }# do your processing here!    print &quot;  $line\n&quot;;}&lt;/pre&gt;This little program will process anything that comes in on the specified port, clearing carriage returns and line feeds, and (in this simple case) spitting it back with two spaces in front and a newline at the end. An input containing &quot;endit&quot; causes the handler to exit, and, thanks to the flush sequence at the top, output is immediate. Make your program executable:&lt;pre class=&quot;block_code&quot;&gt;# chmod +x /usr/local/bin/sinet.pl&lt;/pre&gt;&lt;BR&gt;&lt;BR&gt;&lt;B&gt;The configuration:&lt;/b&gt;&lt;BR&gt;&lt;BR&gt;Okay, now, here&#39;s the setup. In /etc (you need to be superuser), edit /etc/services to add your port number to the known services list, making up a unique name for the service. My port is 6100, its service is &#39;secshsms&#39;, and I&#39;ve asked it to handle both stream (tcp) and datagram (udp) packets, although this example will only deal with tcp.&lt;pre class=&quot;block_code&quot;&gt;secshsms6100/tcp   # DSW Handler for SECS-II/GEM HSMS trafficsecshsms6100/udp   # DSW&lt;/pre&gt;Next, edit /etc/inetd.conf to attach your program to that service:&lt;pre class=&quot;block_code&quot;&gt;# DSW add-on for SECS-II over HSMSsecshsmsstreamtcpnowaitnobody/usr/local/bin/sinet.pl secshsms&lt;/pre&gt;Okay, find inetd and restart it.&lt;pre class=&quot;block_code&quot;&gt;# ps -ax | grep inetd  563  ??  Is      0:00.01 /usr/sbin/inetd -wW -C 60# kill -1 563&lt;/pre&gt;From now on, any process that attempts to talk to my machine&#39;s port 6100 gets its output routed to my handler sinet.pl.&lt;BR&gt;&lt;BR&gt;With that in hand, here&#39;s a sample client, adapted from Perl Cookbook recipe 17.10. It can be installed on any machine within a routable network (i.e., no firewall) and it will talk to my handler.&lt;BR&gt;&lt;BR&gt;&lt;B&gt;A simple client:&lt;/B&gt; &lt;BR&gt;&lt;BR&gt;&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perl# ncliauto.pl a simple automated clientuse warnings;use strict;use IO::Socket;my ( $confstr, $host, $port, $kidpid, $handle, $line, @say );# the config file contains host name (or IP addr) and port number, with a space between# examples:  localhost 6100#            myserv.mynet.com 6100#            123.456.789.1 6100open( CONF, &quot;&lt;./hsms.conf&quot;) or die &quot;conf file: $!\n&quot;;$confstr = &lt;CONF&gt;;close( CONF ) or die &quot;closing conf file: $!\n&quot;;chomp $confstr;( $host, $port ) = split( /\s+/, $confstr );# This is our demo array of outputs sent to the handler@say = ( &#39;You are getting sleepy...&#39;, &#39;... very sleepy.&#39;, &#39;Your eyes are getting very heavy!&#39;, &quot;... it&#39;s so hard to hold them open.&quot;, &quot;You&#39;re so very sleepy now.&quot;, &#39;You just want to go to sleep.&#39;, &#39;Sleep feels so good!&#39;, &quot;You&#39;re asleep. Sleep!&quot;, &quot;You&#39;ve earned it, just relax and sleep!&quot;, &quot;... Sleep!&quot;, &quot;              Sleep!&quot;, &quot;                        Sleep!&quot;, &#39;&#39;, &#39;... zzz... zzz... ...zzz ...&#39;, &#39;endit&#39;);# This creates our client socket$handle = IO::Socket::INET-&gt;new( Proto =&gt; &quot;tcp&quot;, PeerAddr =&gt; $host, PeerPort =&gt; $port )    or die &quot;can&#39;t connect to port &#39;$port&#39; on host &#39;$host&#39;: $!\n&quot;;# make sure it turns around inputs immediately$handle-&gt;autoflush(1);# announce our connectionprint STDERR &quot;[connected to $host:$port]\n&quot;;# fork a child to handle sending our data to the socketdie &quot;can&#39;t fork: $!\n&quot; unless defined($kidpid = fork());if ( $kidpid ){#   The parent handles data coming from the socket server to us    while ( defined( $line = &lt;$handle&gt; ) )    {print STDOUT $line;    }#   ... until the connection is broken    kill( &quot;TERM&quot; =&gt; $kidpid );}else{#   The child process receives data for us    foreach my $item ( @say )    {print $handle $item . &quot;\r\n&quot;;sleep 1;    } }exit;&lt;/pre&gt;Working from this skeleton, a more elaborate language can be developed. The program on each end can be made to parse and respond to commands from the other.&lt;BR&gt;&lt;BR&gt;UPDATE 1: changed server user to nobody, thank you [idsfa].&lt;/READMORE&gt;&lt;div class=&quot;pmsig&quot;&gt;&lt;div class=&quot;pmsig-420266&quot;&gt;&lt;BR&gt;&lt;EM&gt;Don Wilde&lt;/EM&gt;&lt;BR&gt;&lt;FONT COLOR=&#39;#4F8EFF&#39;&gt;&quot;&lt;i&gt;There&#39;s more than one level to any answer.&lt;/i&gt;&quot;&lt;/FONT&gt;&lt;/div&gt;&lt;/div&gt;
    </description>
</item>

        

<item>
    <title>Gay (Anonymous Monk)</title>
    <link>http://prlmnks.org/html/542155.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/542155.html</guid>

    <description>
        UR GAY U STUPID BIATCH
    </description>
</item>

        

<item>
    <title>Module::Compile (or: what&#39;s this PMC thingy?) (Juerd)</title>
    <link>http://prlmnks.org/html/536132.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/536132.html</guid>

    <description>
        &lt;p&gt;&lt;i&gt;This document is written in response to many questions triggered by [id://536101]. It&#39;s not useful as a tutorial, because Module::Compile is in its infancy and very likely to change further, but posted here because it provides information only.&lt;/i&gt;&lt;/p&gt;&lt;h4&gt;History&lt;/h4&gt;&lt;p&gt;Once upon a time, people thought that maybe Perl would be faster if compiled code could be re-used in a later session. (Actually, many people still do.) So they created support for compiled Perl Modules, and where Python libraries got their &quot;c&quot; after their &quot;py&quot;, compiled Perl modules would get their &quot;c&quot; after their &quot;pm&quot;, and the &quot;pmc&quot; extension was born.&lt;/p&gt;&lt;p&gt;It works somewhat like this: you have a module, say, Test.pm, and the following line gives you the compiled version:&lt;pre class=&quot;block_code&quot;&gt;perl -MO=Bytecode,-H -MTest -e1 &gt; Test.pmc&lt;/pre&gt;Provided that Test.pmc is in the same directory that Test.pm is, perl will automatically load Test.pmc instead of Test.pm the next time someone uses &quot;use Test&quot; or &quot;require Test&quot;. This is because in every directory of @INC, perl first sees if a .pmc exists, and if it does, it loads that, and if not, then it tries to load the .pm.&lt;/p&gt;&lt;h4&gt;What&#39;s going on?&lt;/h4&gt;&lt;p&gt;If you strace the process, you can easily see what was going on before:&lt;pre class=&quot;block_code&quot;&gt;stat64(&quot;/usr/local/lib/perl/5.8.7/Test.pmc&quot;, 0x7fe20a50) = -1 ENOENT (No such file or directory)open(&quot;/usr/local/lib/perl/5.8.7/Test.pm&quot;, O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)stat64(&quot;/usr/local/share/perl/5.8.7/Test.pmc&quot;, 0x7fe20a50) = -1 ENOENT (No such file or directory)open(&quot;/usr/local/share/perl/5.8.7/Test.pm&quot;, O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)stat64(&quot;/usr/lib/perl5/Test.pmc&quot;, 0x7fe20a50) = -1 ENOENT (No such file or directory)open(&quot;/usr/lib/perl5/Test.pm&quot;, O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)stat64(&quot;/usr/share/perl5/Test.pmc&quot;, 0x7fe20a50) = -1 ENOENT (No such file or directory)open(&quot;/usr/share/perl5/Test.pm&quot;, O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)stat64(&quot;/usr/lib/perl/5.8/Test.pmc&quot;, 0x7fe20a50) = -1 ENOENT (No such file or directory)open(&quot;/usr/lib/perl/5.8/Test.pm&quot;, O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)stat64(&quot;/usr/share/perl/5.8/Test.pmc&quot;, 0x7fe20a50) = -1 ENOENT (No such file or directory)open(&quot;/usr/share/perl/5.8/Test.pm&quot;, O_RDONLY|O_LARGEFILE) = 4&lt;/pre&gt;Before perl finds Test.pm in /usr/share/perl/5.8, it first tries a lot of other directories, each time stat()ing Test.pmc first, and then trying to open Test.pm. Now, because I have created a Test.pm in /usr/share/perl/5.8, perl&#39;s done a little earlier:&lt;pre class=&quot;block_code&quot;&gt;stat64(&quot;/usr/local/lib/perl/5.8.7/Test.pmc&quot;, 0x7f95aa50) = -1 ENOENT (No such file or directory)open(&quot;/usr/local/lib/perl/5.8.7/Test.pm&quot;, O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)stat64(&quot;/usr/local/share/perl/5.8.7/Test.pmc&quot;, 0x7f95aa50) = -1 ENOENT (No such file or directory)open(&quot;/usr/local/share/perl/5.8.7/Test.pm&quot;, O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)stat64(&quot;/usr/lib/perl5/Test.pmc&quot;, 0x7f95aa50) = -1 ENOENT (No such file or directory)open(&quot;/usr/lib/perl5/Test.pm&quot;, O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)stat64(&quot;/usr/share/perl5/Test.pmc&quot;, 0x7f95aa50) = -1 ENOENT (No such file or directory)open(&quot;/usr/share/perl5/Test.pm&quot;, O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)stat64(&quot;/usr/lib/perl/5.8/Test.pmc&quot;, 0x7f95aa50) = -1 ENOENT (No such file or directory)open(&quot;/usr/lib/perl/5.8/Test.pm&quot;, O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)stat64(&quot;/usr/share/perl/5.8/Test.pmc&quot;, {st_mode=S_IFREG|0644, st_size=720, ...}) = 0stat64(&quot;/usr/share/perl/5.8/Test.pm&quot;, {st_mode=S_IFREG|0644, st_size=28863, ...}) = 0open(&quot;/usr/share/perl/5.8/Test.pmc&quot;, O_RDONLY|O_LARGEFILE) = 4&lt;/pre&gt;Don&#39;t be fooled by the stat() on Test.pm; it&#39;s ignored. The actual open() is now on Test.pmc instead of Test.pm.&lt;/p&gt;&lt;h4&gt;Sad ending&lt;/h4&gt;&lt;p&gt;So, why did (and does) nobody really use this? Well, it turns out that bytecode loading is indeed faster in some (but not all) cases, but not very reliable: segfaults are quite common, and nobody so far has been able to fix it.&lt;/p&gt;&lt;p&gt;But there is another problem with Byteloader. The PMC file is actually just a normal Perl file: via a source filter, the bytecode is loaded. That&#39;s nasty, and makes using precompiled bytecode even less interesting.&lt;/p&gt;&lt;p&gt;Thus a sad story seemed to end, and the PMC feature was ignored, forgotten, and almost about to be deprecated... (Features aren&#39;t removed lightly in Perl - even if nobody uses it, a deprecation cycle is needed.)&lt;/p&gt;&lt;h4&gt;Joyful rebirth of PMC and source filters&lt;/h4&gt;&lt;p&gt;... if it weren&#39;t for the incredible geniuses who work on Perl 6 to find a very neat way to use the PMC feature to make Perl 6 acceptance and initial use less painful!&lt;/p&gt;&lt;p&gt;But actually, it&#39;s not even really Perl 6 related. It&#39;s just a very neat thing that you can also put to good use if you don&#39;t want to use Perl 6 yet. You see, we have source filters that can do very nice and spiffy (no pun intended) things for us, but are also known to have certain negative feelings attached to them. Sourcefilters have problems with mod_perl and other embedded perls, and they cannot be combined with other source filters. Besides that, source filters are always runtime overhead, and the result is usually not cached anywhere. You can&#39;t even debug the result easily, because the intermediate code is not available on disk.&lt;/p&gt;&lt;p&gt;The new invention exists in the form of [cpan://Module::Compile], formerly (for less than a day &amp;mdash; that&#39;s how fast things go in Freenode #perl6) known as PMC::Filter.&lt;/p&gt;&lt;p&gt;Instead of using the normal source filters, Module::Compile writes the &quot;compiled&quot; code to a .pmc file, and that&#39;s loaded from that point forward. The nice trick is that the PMC file doesn&#39;t have to be bytecode. It&#39;s just a normal pure Perl file.&lt;/p&gt;&lt;h4&gt;But we call them compilers now&lt;/h4&gt;&lt;p&gt;A &quot;compiler&quot; (read: source filter) is built quite easily:&lt;pre class=&quot;block_code&quot;&gt;package Foo;use Module::Compile -base;sub pmc_compile {    my ($class, $source) = @_;    # Convert $source into (most like Perl 5) $compiled_output    return $compiled_output;}1;&lt;/pre&gt;and using that is also very straight forward:&lt;pre class=&quot;block_code&quot;&gt;# Unfiltered code herequux(bar);use Foo;# This code is filtered!# Ehh... I mean compiled!no Foo;# Unfiltered code here, againquux(bar);&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;A nice solution for everyone who has found a good use for source filters, but doesn&#39;t use them. Module::Compile supports using multiple compilers (source filters, for those who still don&#39;t get it) at the same time, the intermediate code is available for simpler debugging, and it works well even with embedded perls.&lt;/p&gt;&lt;h4&gt;Perl 6 again&lt;/h4&gt;&lt;p&gt;Remember that it was Perl 6 people that invented all this? It must have something to do with Perl 6, then, right? Well, but of course! The idea is to compile Perl 6 code into Perl 5 code, so that you can use it without Perl 6. You can do this to have a module that has parts in Perl 5 and parts in Perl 6, which is nice if you want to upgrade an existing module with some of the nice new features that Perl 6 has to offer, but don&#39;t want to rewrite everything just yet.&lt;/p&gt;&lt;p&gt;An even nicer thing, though, is that this allows you to write modules that are fully Perl 6, that will work both in Perl 5 and Perl 6.&lt;/p&gt;&lt;h4&gt;Distribution&lt;/h4&gt;&lt;p&gt;There are two problems with the PMC technique, though:&lt;ol&gt;&lt;li&gt; You need to have all the stuff installed that is needed for a succesful compilation&lt;li&gt; Users don&#39;t have write access in the system library directories&lt;/ol&gt;But there is one solution that solves both these problems: let Module::Compile generate your PMCs as you develop your software, and when you&#39;re done, distribute the compiled result along with the rest, so that people can use that. Also, if the PMC is installed with the rest, then someone with superuser privileges installs it.&lt;/p&gt;&lt;h4&gt;Perl 6 example&lt;/h4&gt;&lt;p&gt;Oh, you want example code, of course! Here it is, again copied straight from Module::Compile&#39;s documentation:&lt;pre class=&quot;block_code&quot;&gt;# User.pmuse v6-pugs;module User;...some p6 code here...no v6;...back to p5 land...&lt;/pre&gt;Oh well, I&#39;ll steal their explanation too:&lt;/p&gt;&lt;p&gt;&lt;em&gt;On the first time this module is loaded, it will compile Perl 6 chunks into Perl 5 (as soon as the no v6 line is seen), and merge it with the Perl 5 chunks, saving the result into a User.pmc file.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;The next time around, Perl 5 will automatically load User.pmc when someone says use Foo. On the other hand, Perl 6 can run User.pm as a Perl 6 module just fine, as &quot;use v6-pugs&quot; and &quot;no v6&quot; both works in a perl 6 setting also.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;The pmc module will imbue v6.pm with the ability to check for Foo.pmc&#39;s updatedness also, and if it&#39;s up to date, then it&#39;d touch its timestamp so the .pmc is loaded on the next time.&lt;/em&gt;&lt;/p&gt;&lt;h4&gt;Final words&lt;/h4&gt;&lt;p&gt;And that&#39;s why you shouldn&#39;t disable the PMC feature in Perl: although unused since its invention in 1999, there&#39;s now a very powerful use for it! Fortunately, so far the survey shows that only Mandrake/Mandriva users have it disabled. They can fix it soon, by upgrading.&lt;/p&gt;&lt;p&gt;Do note that Perl 6 is very far from production quality, and that Module::Compile is also still very young. You should probably not use them for anything serious yet.&lt;/p&gt;&lt;p&gt;Thank you, ingy++ and audreyt++, for bringing us this wonderful innovation!&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>Using Look-ahead and Look-behind (Roy Johnson)</title>
    <link>http://prlmnks.org/html/518444.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/518444.html</guid>

    <description>
        If you are familiar with Perl&#39;s regular expressions, you are probably already familiar with zero-width assertions: the &lt;tt class=&quot;inline_code&quot;&gt;^&lt;/tt&gt; indicating the beginning of string and the &lt;tt class=&quot;inline_code&quot;&gt;\b&lt;/tt&gt; indicating a word boundary are examples. They do not match any characters, but &quot;look around&quot; to see what comes before and/or after the current position.&lt;p&gt;With the look-ahead and look-behind constructs documented in &lt;a href=&quot;/out/http/?url=perldoc.perl.org%2Fperlre.html%23Extended-Patterns&quot;&gt;perlre.html#Extended-Patterns&lt;/a&gt;, you can &quot;roll your own&quot; zero-width assertions to fit your needs. You can look forward or backward in the string being processed, and you can require that a pattern match succeed (positive assertion) or fail (negative assertion) there.&lt;h3&gt;Syntax&lt;/h3&gt;Every extended pattern is written as a parenthetical group with a question mark as the first character. The notation for the look-arounds is fairly mnemonic, but there are some other, experimental patterns that are similar, so it is important to get all the characters in the right order. &lt;dl&gt;&lt;dt&gt;&lt;tt class=&quot;inline_code&quot;&gt;(?=&lt;/tt&gt;&lt;i&gt;pattern&lt;/i&gt;&lt;tt class=&quot;inline_code&quot;&gt;)&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;is a positive look-ahead assertion&lt;/dd&gt;&lt;dt&gt;&lt;tt class=&quot;inline_code&quot;&gt;(?!&lt;/tt&gt;&lt;i&gt;pattern&lt;/i&gt;&lt;tt class=&quot;inline_code&quot;&gt;)&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;is a negative look-ahead assertion&lt;/dd&gt;&lt;dt&gt;&lt;tt class=&quot;inline_code&quot;&gt;(?&lt;=&lt;/tt&gt;&lt;i&gt;pattern&lt;/i&gt;&lt;tt class=&quot;inline_code&quot;&gt;)&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;is a positive look-behind assertion&lt;/dd&gt;&lt;dt&gt;&lt;tt class=&quot;inline_code&quot;&gt;(?&lt;!&lt;/tt&gt;&lt;i&gt;pattern&lt;/i&gt;&lt;tt class=&quot;inline_code&quot;&gt;)&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;is a negative look-behind assertion&lt;/dd&gt;&lt;/dl&gt;Notice that the &lt;tt class=&quot;inline_code&quot;&gt;=&lt;/tt&gt; or &lt;tt class=&quot;inline_code&quot;&gt;!&lt;/tt&gt; is always last. The directional indicator is only present in the look-behind, and comes before the positive-negative indicator.&lt;h3&gt;Common tasks&lt;/h3&gt;&lt;h4&gt;Finding the last occurrence&lt;/h4&gt;There are actually a number of ways to get the last occurrence that don&#39;t involve look-around, but if you think of &quot;the last foo&quot; as &quot;foo that isn&#39;t followed by a string containing foo&quot;, you can express that notion like this:&lt;pre class=&quot;block_code&quot;&gt;/foo(?!.*foo)/&lt;/pre&gt;The regular expression engine will do its best to match &lt;tt class=&quot;inline_code&quot;&gt;.*foo&lt;/tt&gt;, starting at the end of the string &quot;foo&quot;. If it is able to match that, then the negative look-ahead will fail, which will force the engine to progress through the string to try the next foo.&lt;h4&gt;Substituting before, after, or between characters&lt;/h4&gt;Many substitutions match a chunk of text and then replace part or all of it. You can often avoid that by using look-arounds. For example, if you want to put a comma after every foo:&lt;pre class=&quot;block_code&quot;&gt;s/(?&lt;=foo)/,/g; # Without lookbehind: s/foo/foo,/g or s/(foo)/$1,/g&lt;/pre&gt;or to put the hyphen in look-ahead:&lt;pre class=&quot;block_code&quot;&gt;s/(?&lt;=look)(?=ahead)/-/g;&lt;/pre&gt;This kind of thing is likely to be the bulk of what you use look-arounds for. It is important to remember that &lt;b&gt;look-behind expressions cannot be of variable length&lt;/b&gt;. That means you cannot use quantifiers (&lt;tt class=&quot;inline_code&quot;&gt;., +, or {1,5}&lt;/tt&gt;) or alternation of different-length items inside them.&lt;h4&gt;Matching a pattern that doesn&#39;t include another pattern&lt;/h4&gt;You might want to capture everything between foo and bar that doesn&#39;t include baz. The technique is to have the regex engine look-ahead at every character to ensure that it isn&#39;t the beginning of the undesired pattern:&lt;pre class=&quot;block_code&quot;&gt;/foo  # Match starting at foo (?:       # Complex expression:   (?!baz) #   make sure we&#39;re not at the beginning of baz    .       #   accept any character )*        # any number of times bar  # and ending at bar/x;&lt;/pre&gt;&lt;h3&gt;Nesting&lt;/h3&gt;You can put look-arounds inside of other look-arounds. This has been known to induce a flight response in certain readers (me, for example, the first time I saw it), but it&#39;s really not such a hard concept. A look-around sub-expression inherits a starting position from the enclosing expression, and can walk all around relative to that position without affecting the position of the enclosing expression. They all have independent (though initially inherited) bookkeeping for where they are in the string.&lt;p&gt;The concept is pretty simple, but the notation becomes hairy very quickly, so commented regular expressions are recommended. Let&#39;s look at the real example of [id://319742]. The poster wants to put a space after any comma (punctuation, actually, but for simplicity, let&#39;s say comma) that is not nestled between two digits. Building up the s/// expression:&lt;pre class=&quot;block_code&quot;&gt;s/(?&lt;=,        # after a comma,    (?!        # but not matching      (?&lt;=\d,) #   digit-comma before, AND      (?=\d)   #   digit afterward    )  )/ /gx;      # substitute a space&lt;/pre&gt;Note that multiple lookarounds can be used to enforce multiple conditions at the same place, like an AND condition that complements the alternation (vertical bar)&#39;s OR. In fact, you can use Boolean algebra ( &lt;tt class=&quot;inline_code&quot;&gt;NOT (a AND b) === (NOT a OR NOT b)&lt;/tt&gt; ) to convert the expression to use OR:&lt;pre class=&quot;block_code&quot;&gt;s/(?&lt;=,        # after a comma, but either    (?:      (?&lt;!\d,) #   not matching digit-comma before      |        #   OR      (?!\d)   #   not matching digit afterward    )  )/ /gx;      # substitute a space&lt;/pre&gt;&lt;h3&gt;Capturing&lt;/h3&gt;It is sometimes useful to use capturing parentheses within a look-around. You might think that you wouldn&#39;t be able to do that, since you&#39;re just browsing, but [478043|you can]. But remember: the capturing parentheses must be within the look-around expression; from the enclosing expression&#39;s point of view, no actual matching was done by the zero-width look-around.
    </description>
</item>

        

<item>
    <title>Creating COM and DCOM objects with Perl (JamesNC)</title>
    <link>http://prlmnks.org/html/516137.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/516137.html</guid>

    <description>
        Ok, you have a written a really cool perl program and you would like to use if from MSExcel or MSWord or from a WSH or VB script.  Perhaps it is an interface to DBI or some other really great perl module.  How do you do it?  &lt;br&gt;This short tutorial for Win32 users explains how and give examples of how to share perl $scalars, @arrays and %hashes using a WSC - Windows Scripting Component to local and networked users.  The documentation shows much more info. This tutorial is a just a quick and dirty how to get it working along with some stuff I have learned that is NOT in the documentation like how to do hashes( mimicked )&lt;br&gt;This tutorial also assumes that you know some VBA and how to open up the VB Editor in Excel.&lt;br&gt;Helpful links:&lt;li&gt; &lt; a href=&quot;http://www.microsoft.com/downloads/details.aspx?FamilyId=408024ED-FAAD-4835-8E68-773CCC951A6B&amp;displaylang=en &quot; &gt;WSC Wizard&lt;/a&gt; &lt;i&gt;Technically optional, but I would get this free tool that generates a .wsc framework for you.&lt;/i&gt;&lt;li&gt; &lt; a href=&quot;http://www.microsoft.com/downloads/details.aspx?familyid=C717D943-7E4B-4622-86EB-95A22B832CAA&amp;displaylang=en&quot; &gt;WSH &lt;/a&gt; &lt;i&gt;Optional on W2K/XP&lt;/i&gt;&lt;li&gt;&lt;a href=&quot;http://www.microsoft.com/downloads/details.aspx?familyid=01592C48-207D-4BE1-8A76-1C4099D7BBB9&amp;displaylang=en&quot; &gt; WSC and WSH Documentation &lt;/a&gt;&lt;p&gt;The process is fairly simple.&lt;ol&gt;&lt;li&gt; Create a .WSC file ( recommend using the Wizard )&lt;li&gt; Add Perl and/or Perlscript code to the .WSC file&lt;li&gt; Register the .WSC COM object with windows&lt;li&gt; In your VB code, use CreateObject to create a instance of the COM object&lt;/ol&gt;Now on to the examples!&lt;/p&gt;&lt;i&gt;Copy and paste the following code into a file named &quot;pcom.WSC&quot; ( Note: do not alter the classid in this file! )&lt;/i&gt;&lt;pre class=&quot;block_code&quot;&gt;&lt;?xml version=&quot;1.0&quot;?&gt;&lt;component&gt;&lt;?component debug=&quot;true&quot; ?&gt;&lt;registrationdescription=&quot;pcom&quot;progid=&quot;pcom.WSC&quot;version=&quot;1.00&quot;remotable=&quot;true&quot;classid=&quot;{e91a2a76-18bc-4ab0-8b1c-06d6d0442287}&quot;&gt;&lt;/registration&gt;&lt;public&gt;&lt;method name=&quot;sortList&quot;&gt;        &lt;parameter name=&quot;vbArray&quot;/&gt;&lt;/method&gt;&lt;method name=&quot;getHash&quot;&gt;&lt;/method&gt;&lt;method name=&quot;getScalar&quot;&gt;&lt;parameter name=&quot;scalar&quot;/&gt;&lt;/method&gt;&lt;/public&gt;&lt;script language=&quot;PerlScript&quot;&gt;&lt;![CDATA[# Author: James Moosmann# Copyright 2005use Win32::OLE::Variant;sub sortList{my @list = @_;@list = sort @list;my $ary = convertArrayToVBArray( \@list );return $ary;}sub getHash{my @input = @_;my %dog = ( &quot;buddy&quot; =&gt; &quot;dog&quot; , &quot;georgie&quot;, &quot;dog&quot; );my $hash = convertHashToDict(\%dog);return $hash;}sub getScalar{my $scalar = $_[0];if( $scalar =~/^[\d\.]+$/g ){ return $scalar+1; }return $scalar = &quot;perl_saw:$scalar&quot;;}sub convertHashToDict{my $hash_ref = $_[0];my $dict = Win32::OLE-&gt;CreateObject(&quot;Scripting.Dictionary&quot;) or die $!;foreach my $key ( keys %{$hash_ref} ){  $dict-&gt;add( $key, ${$hash_ref}{$key} ); }return $dict;}sub convertArrayToVBArray{my $array_ref = $_[0];my $ary = Variant( VT_ARRAY|VT_VARIANT, $#{$array_ref}+1);$ary-&gt;Put(\@{$array_ref});return $ary;}]]&gt;&lt;/script&gt;&lt;/component&gt;&lt;/pre&gt;After you create the above file on your system.  Then you just need to Register it with windows. In windows this is simple.&lt;ol&gt;&lt;li&gt; Right click on the file&lt;li&gt; Select -&gt; Register&lt;/ol&gt;Whew!  That was tough.&lt;br&gt;&lt;i&gt;**You may also notice the &quot;Generate Type Library&quot; and wonder what it does.  If it worked, it would help open up the api to your COM object and things like autocomplete in the VB editor would work for you. It kind of works in that if you were to create the typelib and then go to Excel and create a refrence to it, things would seem to work.  But at run time when the COM object gets created, it is always the wrong type (Variant/Object) vs the Object that you created. So, don&#39;t even bother.  Microsoft knows about this error and acknowledges it, but doesn&#39;t disable the &quot;feature&quot;... bizarre&lt;/i&gt;&lt;p&gt;Ok, we have Registered our COM object.  Now, we need to use it!  Here&#39;s how using Excel:&lt;br&gt;&lt;i&gt;Open a blank Excel sheet and add the following code&lt;/i&gt;&lt;pre class=&quot;block_code&quot;&gt;Sub sortList_test()Set obj = CreateObject(&quot;pcom.WSC&quot;)Dim l() As Variantl = obj.sortList(&quot;fox&quot;, &quot;dog&quot;, &quot;moose&quot;, &quot;cat&quot;, &quot;fish&quot;) For Each li In l    Debug.Print li    Next liEndEnd SubSub getHash_test()Set obj = CreateObject(&quot;pcom.WSC&quot;)Dim hash As Scripting.DictionarySet hash = obj.getHash(&quot;dogHash&quot;)Debug.Print &quot;Buddy is my &quot; &amp; hash.Item(&quot;buddy&quot;)End SubSub getScalar_test()Set obj = CreateObject(&quot;pcom.WSC&quot;)scalar = obj.getScalar(1)Debug.Print scalarscalar = obj.getScalar(&quot;a string! from VB&quot;)Debug.Print scalarEnd Sub&lt;/pre&gt;&lt;p&gt;&lt;i&gt;Make sure that you have References to &quot;Microsoft Scriptlet Library&quot; and &quot;Microsoft Scripting Runtime&quot; selected. &lt;/i&gt;Call the subs and that&#39;s it for the fast track intro. I will elaborate more below on DCOM and a few more selected details. &lt;/p&gt;&lt;br&gt;&lt;p&gt;What about DCOM?  Why use it? &lt;br&gt;Your office mate on the same network doesn&#39;t have Perl installed on his box, but he wants to use your nifty perl object.  DCOM comes to the rescue!  Here are the steps needed to allow a user on another computer have access to the object. (Since this is documented in the above links I am only going to give an outline, search the docs for more details.)&lt;ol&gt;&lt;li&gt; You need to modify the pcom.WSC file and add remotableattribute (be careful of the spelling! it is NOT remoteable) to the &lt;registration ... &gt; section like so:&lt;br&gt;&lt;pre class=&quot;block_code&quot;&gt;&lt;registrationdescription=&quot;pcom&quot;progid=&quot;pcom.WSC&quot;version=&quot;1.00&quot;classid=&quot;{e91a2a76-18bc-4ab0-8b1c-06d6d0442287}&quot;        remotable=&quot;true&quot;&gt;&lt;/registration&gt;&lt;/pre&gt;Now, you can call the object by using the the 2 argument form of CreateObject in your VB like so...&lt;pre class=&quot;block_code&quot;&gt;Set hash = obj.getHash(&quot;dogHash&quot;, &quot;127.0.0.1&quot;)&lt;/pre&gt;If you tried this, it would fail on your friends computer because you have to first register your object on his machine AND you need to give him permission to use that object from your computer. &lt;br&gt;&lt;p&gt;How to register your COM object on his computer&lt;ol&gt; &lt;li&gt; Open up regedit and search for pcom.WSC&lt;li&gt; Right-click on the &quot;{e91a2a76-18bc-4ab0-8b1c-06d6d0442287}&quot; entry (pcom.WSC&#39;s classid ) and then select Export from the popup menu.&lt;li&gt; Save this registry entry as pcom.reg&lt;/ol&gt;&lt;p&gt;Now, you just can use this file to add the needed information to his registry.  Copy the file to your friends computer and Merge the file with his registry. ( You can do that with a Right-click and select Merge )&lt;p&gt;You are 1/2 way there.  Now, you need to give him permission to access the object on your machine.  You do that with &quot;dcomcnfg.exe&quot;. This utility has a different interface for W2K and XP, so I will let you figure this part out.  Basically, after you add the remotable entry, you will need to re-register the pcom.WSC file again, then open dcomcnfg.exe and browse the the pcom object and set the permissions for that object as appropriate. &lt;i&gt;See the documentation for more details on how to run the object with different credentials.  You can set security on the objects and more with the utility!&lt;/i&gt;&lt;p&gt; What about debugging?&lt;br&gt;The docs again.  But my take on it is obviously debug your perl separately or in a .vb script where you can see the output more easily.&lt;p&gt;Well, that&#39;s it.  Hope it will open the world of amazing things perl can do with great ease and power to spread sheets and and other Windows applications for you.  &lt;br&gt;Other options I did not talk about include some solutions from ActiveState. They have some commercially available tools that can turn your scripts into stand alone controls and services, system tray utilities, apps and more.  I don&#39;t work for them, but their PDK - Perl Dev Kit is worth the money IMHO if you want more robust features of doing these types of things.&lt;p&gt;Cheers, &lt;br&gt;JamesNC
    </description>
</item>

        

<item>
    <title>Test adding tutorial (wl69)</title>
    <link>http://prlmnks.org/html/511037.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/511037.html</guid>

    <description>
        I am doing a reseach project about the web community. I just test adding a tutorial without logging into the community. I am so sorry about messing up the tutorial section. If anyone has authority to delete the node, please go ahead! I appreciate that!
    </description>
</item>

        

<item>
    <title>How A Function Becomes Higher Order (Limbic~Region)</title>
    <link>http://prlmnks.org/html/492651.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/492651.html</guid>

    <description>
        All:&lt;br /&gt;[isbn://1558607013|Higher Order Perl], by [Dominus], has become a very popular book.  It was written to teach programmers how to transform programs with programs.  Many of us who do not have familiarity with Functional Programming are not aware of what [http://en.wikipedia.org/wiki/Higher-order_function|Higher Order] functions are.  It is a function that does at least on of the two following things:&lt;ul&gt;&lt;li&gt;Accepts a function as input&lt;/li&gt;&lt;li&gt;Returns a function as output&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;This tutorial is an illustration of how a simple every day function may become higher order increasing its usefulness in the process.  Along the way we will pick up other tricks that can make our code more flexible and useful.&lt;/p&gt;&lt;H4&gt;Problem: We have a file containing a list of scores and we need to determine the highest score.&lt;/H4&gt;&lt;p&gt;Using the principal of code reuse and not reinventing the wheel, we turn to our trusty [cpan://List::Util].&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;use List::Util &#39;max&#39;;my @scores = &lt;FH&gt;;my $high_score = max(@scores);&lt;/pre&gt;&lt;p&gt;Unfortunately, this requires all of the scores to be held in memory at one time and our file is really big.  Just this once, we decide to break the rules and roll our own.&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;my $high_score;while ( &lt;FH&gt; ) {    chomp;    $high_score = $_ if ! defined $high_score || $_ &gt; $high_score;}&lt;/pre&gt;&lt;p&gt;As time goes by &quot;just this once&quot; has happened many times and we decide to make our version reuseable. &lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;sub gen_max {    my $max;    $max = $_[0] if defined $_[0];    return sub {        for ( @_ ) {            $max = $_ if ! defined $max || $_ &gt; $max;        }        return $max;    };}my $max = gen_max();while ( &lt;FH&gt; ) {    chomp;    $max-&gt;($_);}my $high_score = $max-&gt;();&lt;/pre&gt;&lt;p&gt;This is our first step into Higher Order functions as we have returned a function as the output for the sake of reusability.  We have also have many advantages over the original [cpan://List::Util] &lt;i&gt;max&lt;/i&gt; function.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Does not require all values to be present at once&lt;/li&gt;&lt;li&gt;Ability to define a starting value&lt;/li&gt;&lt;li&gt;Ability to process one or more values at a time&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Unfortunately, our function breaks the second we start comparing strings instead of numbers.  We could make &lt;i&gt;max()&lt;/i&gt; and &lt;i&gt;maxstr()&lt;/i&gt; functions like [cpan://List::Util] but we want to use the concept of Higher Order functions to increase the versatility of our single function.&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;sub gen_reduce {    my $usage = &#39;Usage: gen_reduce(&quot;initial&quot; =&gt; $val, &quot;compare&quot; =&gt; $code_ref)&#39;;    my $val;    die $usage if @_ % 2;    my %opt = @_;    die $usage if ! defined $opt{compare} || ref $opt{compare} ne &#39;CODE&#39;;    my $compare = $opt{compare};    $val = $opt{initial} if defined $opt{initial};    return sub {        for ( @_ ) {            $val = $_ if ! defined $val || $compare-&gt;($_,  $val);        }        return $val;    };}my $maxstr = gen_reduce(compare =&gt; sub { length($_[0]) &gt; length($_[1]) } );while ( &lt;FH&gt; ) {    chomp;    $maxstr-&gt;($_);}my $long_str = $maxstr-&gt;();&lt;/pre&gt;&lt;p&gt;Now our function takes a function as input and returns a function as output.  In addition to the previous functionality, we have added a few more features.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Named parameters - allows flexibility in ordering and presence of arguments as well as ease in extensibility&lt;/li&gt;&lt;li&gt;User defined comparator - our max function has now become a reduce function&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;This does not have to be the end of the journey into Higher Order functions, though it is the end of the tutorial.  Whenever you encounter a situation where two programs do nearly identical things but their differences are enough to make using a single function impossible - consider Higher Order functions to bridge the gap.  Remember - it is important to always document your interface and assumptions well!&lt;/p&gt;&lt;p&gt;I open the floor to comments both on the advantages and disadvantages of Higher Order functions.  As they say, there is no such thing as a free lunch and there are always cases in which it makes sense to use distinct routines for distinct problems.&lt;/p&gt;Cheers,[Limbic~Region|L~R]&lt;p&gt;&lt;small&gt;Note:  [cpan://List::Util] is a great module and the limitation of requiring all the values to be present at once is usually made up for by the fact that it also provides a &lt;i&gt;reduce()&lt;/i&gt; function, has both C and Perl implementations, and syntactic sugar.  The limitations were highlighted here for illustration purposes though I recommend using it when and where it does the job you need it to.&lt;/small&gt;&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>Stepping up from XML::Simple to XML::LibXML (grantm)</title>
    <link>http://prlmnks.org/html/490846.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/490846.html</guid>

    <description>
        &lt;p&gt;If your XML parsing requirements can be boiled down to &quot;&lt;i&gt;slurp an XML file into a hash&lt;/i&gt;&quot;,then XML::Simple is very likely all you need.However,many people who start using [http://search.cpan.org/dist/XML-Simple/|XML::Simple] continue to cling to the module even when their requirements have outgrown it.Most often,it&#39;s fear of the unknown that keeps them from &#39;stepping up&#39;; to a more capable module.In this article,I&#39;m going to attempt to dispel some of that fear by comparing using [http://search.cpan.org/dist/XML-LibXML/|XML::LibXML] to using XML::Simple.&lt;/p&gt;&lt;h2&gt;Installation&lt;/h2&gt;&lt;p&gt;If you&#39;re running Windows,you can get a binary build of XML::LibXML from Randy Kobes&#39; [http://theoryx5.uwinnipeg.ca/|PPM repositories].If you&#39;re running Linux then things will be even simpler - just use the package from your distribution (eg: on Debian: apt-get install libxml-libxml-perl).&lt;/p&gt;&lt;p&gt;If for some reason you&#39;re unable to install XML::LibXML,but you have XML::Parser,then you might like to install XML::XPath which is a Pure Perl module that implements a very similar API to LibXML but uses XML::Parser for the parsing bit.&lt;/p&gt;&lt;h2&gt;Some Sample Data&lt;/h2&gt;&lt;p&gt;Let&#39;s start with a file that lists the details of books in a (very small) library:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;  &lt;library&gt;    &lt;book&gt;      &lt;title&gt;Perl Best Practices&lt;/title&gt;      &lt;author&gt;Damian Conway&lt;/author&gt;      &lt;isbn&gt;0596001738&lt;/isbn&gt;      &lt;pages&gt;542&lt;/pages&gt;      &lt;image src=&quot;http://www.oreilly.com/catalog/covers/perlbp.s.gif&quot;             width=&quot;145&quot; height=&quot;190&quot; /&gt;    &lt;/book&gt;    &lt;book&gt;      &lt;title&gt;Perl Cookbook, Second Edition&lt;/title&gt;      &lt;author&gt;Tom Christiansen&lt;/author&gt;      &lt;author&gt;Nathan Torkington&lt;/author&gt;      &lt;isbn&gt;0596003137&lt;/isbn&gt;      &lt;pages&gt;964&lt;/pages&gt;      &lt;image src=&quot;http://www.oreilly.com/catalog/covers/perlckbk2.s.gif&quot;             width=&quot;145&quot; height=&quot;190&quot; /&gt;    &lt;/book&gt;    &lt;book&gt;      &lt;title&gt;Guitar for Dummies&lt;/title&gt;      &lt;author&gt;Mark Phillips&lt;/author&gt;      &lt;author&gt;John Chappell&lt;/author&gt;      &lt;isbn&gt;076455106X&lt;/isbn&gt;      &lt;pages&gt;392&lt;/pages&gt;      &lt;image src=&quot;http://media.wiley.com/product_data/coverImage/6X/07645510/076455106X.jpg&quot;             width=&quot;100&quot; height=&quot;125&quot; /&gt;    &lt;/book&gt;  &lt;/library&gt;&lt;/pre&gt;&lt;h2&gt;A Simple Problem&lt;/h2&gt;&lt;p&gt;As a warm-up exercise, let&#39;s list the titles of all the books from the XML file. Please assume all the code samples begin as follows:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;  #!/usr/bin/perl  use strict;  use warnings;  my $filename = &#39;library.xml&#39;;&lt;/pre&gt;&lt;p&gt;Here&#39;s one solution, using XML::Simple:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;  use XML::Simple qw(:strict);  my $library  = XMLin($filename,    ForceArray =&gt; 1,    KeyAttr    =&gt; {},  );  foreach my $book (@{$library-&gt;{book}}) {    print $book-&gt;{title}-&gt;[0], &quot;\n&quot;   }&lt;/pre&gt;&lt;p&gt;And here&#39;s a LibXML solution that works the same way:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;  use XML::LibXML;  my $parser = XML::LibXML-&gt;new();  my $doc    = $parser-&gt;parse_file($filename);  foreach my $book ($doc-&gt;findnodes(&#39;/library/book&#39;)) {    my($title) = $book-&gt;findnodes(&#39;./title&#39;);    print $title-&gt;to_literal, &quot;\n&quot;   }&lt;/pre&gt;&lt;p&gt;The &lt;tt class=&quot;inline_code&quot;&gt;&#39;/library/book&#39;&lt;/tt&gt; argument to &lt;tt class=&quot;inline_code&quot;&gt;findnodes&lt;/tt&gt; is called an XPath expression. If we substitute a slightly more complex XPath expression, we can factor out one line of code from inside the loop:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;  foreach my $title ($doc-&gt;findnodes(&#39;/library/book/title&#39;)) {    print $title-&gt;to_literal, &quot;\n&quot;   }&lt;/pre&gt;&lt;p&gt;And if it&#39;s code brevity we&#39;re looking for, we can take things even further (this is Perl after all):&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;  print $_-&gt;data . &quot;\n&quot; foreach ($doc-&gt;findnodes(&#39;//book/title/text()&#39;));&lt;/pre&gt;&lt;h2&gt;A More Complex Query&lt;/h2&gt;&lt;p&gt;Now, let&#39;s select a specific book using its ISBN number and list the authors. Using XML::Simple:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;  use XML::Simple qw(:strict);  my $isbn     = &#39;0596003137&#39;;  my $library  = XMLin($filename,     ForceArray =&gt; [ &#39;book&#39;, &#39;author&#39; ],     KeyAttr    =&gt; { book =&gt; &#39;isbn&#39; }  );  my $book = $library-&gt;{book}-&gt;{$isbn};  print &quot;$_\n&quot; foreach(@{$book-&gt;{author}});&lt;/pre&gt;&lt;p&gt;And with LibXML:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;  use XML::LibXML;  my $isbn   = &#39;0596003137&#39;;  my $parser = XML::LibXML-&gt;new();  my $doc    = $parser-&gt;parse_file($filename);  my $query  = &quot;//book[isbn/text() = &#39;$isbn&#39;]/author/text()&quot;;  print $_-&gt;data . &quot;\n&quot; foreach ($doc-&gt;findnodes($query));&lt;/pre&gt;&lt;p&gt;This time, we&#39;ve used a more complex XPath expression to identify both the &lt;tt class=&quot;inline_code&quot;&gt;&lt;book&gt;&lt;/tt&gt; element and the &lt;tt class=&quot;inline_code&quot;&gt;&lt;author&gt;&lt;/tt&gt; elements within it, in a single step. To understand that XPath expression, let&#39;s first consider a simpler one:&lt;/p&gt;&lt;tt class=&quot;inline_code&quot;&gt;  //book[1]&lt;/tt&gt;&lt;p&gt;This expression selects the first in a sequence of consecutive &lt;tt class=&quot;inline_code&quot;&gt;&lt;book&gt;&lt;/tt&gt; elements. The &lt;tt class=&quot;inline_code&quot;&gt;[1]&lt;/tt&gt; is actually a shorthand version of the more general form:&lt;/p&gt;&lt;tt class=&quot;inline_code&quot;&gt;  //book[position() = 1]&lt;/tt&gt;&lt;p&gt;&lt;i&gt;Note XPath positions are numbered from 1 - weird huh?.&lt;/i&gt;&lt;/p&gt;&lt;p&gt;As you can see, the square brackets enclose an expression and the XPath query will match all nodes for which the expression evaulates to true. So to return to the XPath query from our last code sample:&lt;/p&gt;&lt;tt class=&quot;inline_code&quot;&gt;  //book[isbn/text() = &#39;0596003137&#39;]/author/text()&lt;/tt&gt;&lt;p&gt;This will match the text content of any &lt;tt class=&quot;inline_code&quot;&gt;&lt;author&gt;&lt;/tt&gt; elements within a &lt;tt class=&quot;inline_code&quot;&gt;&lt;book&gt;&lt;/tt&gt; element which also contains an &lt;tt class=&quot;inline_code&quot;&gt;&lt;isbn&gt;&lt;/tt&gt; element with the text content &#39;0596003137&#39;. The leading // is kind of a wildcard and will match any number of levels of element nesting. After you&#39;ve re-read that a few times, it might even start to make sense.&lt;/p&gt;&lt;p&gt;The &lt;a href=&quot;/out/http/?url=search.cpan.org%2Fdist%2FXML-XPath%2F&quot;&gt;XML::XPath&lt;/a&gt; distribution includes a command-line tool &#39;xpath&#39; which you can use to test your XPath skills interactively. Here&#39;s an example of querying our file to extract the ISBN of any book over 900 pages long:&lt;/p&gt;&lt;tt class=&quot;inline_code&quot;&gt;  xpath -q -e &#39;//book[pages &gt; 900]/isbn/text()&#39; library.xml&lt;/tt&gt;&lt;p&gt;To achieve the same thing with XML::Simple, you&#39;d need to iterate over the elements yourself:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;  my $library  = XMLin($filename, ForceArray =&gt; [ &#39;book&#39; ], KeyAttr =&gt; {});  foreach my $book (@{$library-&gt;{book}}) {    print $book-&gt;{isbn}, &quot;\n&quot; if $book-&gt;{pages} &gt; 900;  }&lt;/pre&gt;&lt;h2&gt;Modifying the XML&lt;/h2&gt;&lt;p&gt;One area in which XML::Simple is particularly weak is round-tripping an XML file - reading it, modifying the data and writing it back out as XML.&lt;/p&gt;&lt;p&gt;For this example, we&#39;re going to locate the data for the book with ISBN 076455106X and correct its page count from 392 to 394:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;  use XML::Simple qw(:strict);  my $isbn = &#39;076455106X&#39;;  my $xs = XML::Simple-&gt;new(    ForceArray =&gt; 1,    KeyAttr    =&gt; { },    KeepRoot   =&gt; 1,  );  my $ref  = $xs-&gt;XMLin($filename);  my $books = $ref-&gt;{library}-&gt;[0]-&gt;{book};  my($book) = grep($_-&gt;{isbn}-&gt;[0] eq $isbn, @$books);  $book-&gt;{pages}-&gt;[0] = &#39;394&#39;;  print $xs-&gt;XMLout($ref);&lt;/pre&gt;&lt;p&gt;In this example I&#39;ve used a number of tricks to attempt to make the output format resemble the input format as closely as possible:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;an XML::Simple object was used to ensure the exact same options were used both for input and output&lt;/li&gt;&lt;li&gt;the ForceArray option was turned on to ensure that elements didn&#39;t get turned into attributes - unfortunately this necessitates the use of the extra &lt;tt class=&quot;inline_code&quot;&gt;-&gt;[0]&lt;/tt&gt; indexing&lt;/li&gt;&lt;li&gt;the KeyAttr option was used to stop arrays being folded into hashes and thus losing the order of the &lt;code &gt;&lt;book&gt;&lt;/code&gt; elements - unfortunately this necessitates iterating through the elements rather than indexing directly by ISBN&lt;/li&gt;&lt;li&gt;the KeepRoot option was used to ensure the root element name was preserved - unfortunately this introduced an extra level of hash nesting&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Even after disabling all the features that make XML::Simple both simple and convenient, the results are not ideal. Although the order of the books was preserved, the order of the child elements within each book was lost.&lt;/p&gt;&lt;p&gt;By contrast, the LibXML code to perform the same update is both simpler and more accurate:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;  use XML::LibXML;  my $isbn   = &#39;076455106X&#39;;  my $parser = XML::LibXML-&gt;new();  my $doc    = $parser-&gt;parse_file($filename);  my $query  = &quot;//book[isbn = &#39;$isbn&#39;]/pages/text()&quot;;  my($node)  = $doc-&gt;findnodes($query);  $node-&gt;setData(&#39;394&#39;);  print $doc-&gt;toString;&lt;/pre&gt;&lt;h2&gt;Other Operations&lt;/h2&gt;&lt;p&gt;If you need to remove an element from an XML document using XML::Simple, you&#39;d simply delete the appropriate hash key. With LibXML, you would call the &lt;tt class=&quot;inline_code&quot;&gt;removeChild&lt;/tt&gt; method on the element&#39;s parent. For example:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;  my($book)  = $doc-&gt;findnodes(&quot;//book[isbn = &#39;$isbn&#39;]&quot;);  my $library = $book-&gt;parentNode;  $library-&gt;removeChild($book);&lt;/pre&gt;&lt;p&gt;To add an element with XML::Simple you&#39;d add a new key to the hash. With LibXML, you must first create the new element, add any child elements (such as text content) and add it at the right point in the tree. For example:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;  my $rating = $doc-&gt;createElement(&#39;rating&#39;);  $rating-&gt;appendTextNode(&#39;5&#39;);  $book-&gt;appendChild($rating);&lt;/pre&gt;&lt;p&gt;If that looks a bit too complex, there&#39;s also a convenience method you can use to add one element with text content in a single step:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;  $book-&gt;appendTextChild(&#39;rating&#39;, &#39;5&#39;);&lt;/pre&gt;&lt;p&gt;XML::LibXML also provides a very handy method called &lt;tt class=&quot;inline_code&quot;&gt;parse_balanced_chunk&lt;/tt&gt; that allows you to create a collection of related DOM nodes from a string containing an XML fragment. You can then add those nodes to your document:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;  my $fragment = $parser-&gt;parse_balanced_chunk(    &#39;&lt;rating&gt;5&lt;/rating&gt;&lt;price&gt;32.00&lt;/price&gt;&#39;  );  $book-&gt;appendChild($fragment);&lt;/pre&gt;&lt;p&gt;When you call &lt;tt class=&quot;inline_code&quot;&gt;toString&lt;/tt&gt; to output the XML, you&#39;ll find the nodes you&#39;ve added are not nicely indented as they would be with XML::Simple. This is hardly surprising since such indenting would require extra text nodes and if you don&#39;t add them they won&#39;t magically appear. In theory, you can call &lt;tt class=&quot;inline_code&quot;&gt;toString(1)&lt;/tt&gt; to specify you want indents added, but I haven&#39;t had any success with that. You can however pipe the output through:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;  xmllint --format -&lt;/pre&gt;&lt;p&gt;The &lt;tt class=&quot;inline_code&quot;&gt;xmllint&lt;/tt&gt; utility is part of the &lt;tt class=&quot;inline_code&quot;&gt;libxml&lt;/tt&gt; distribution.&lt;/p&gt;&lt;h2&gt;Resources&lt;/h2&gt;&lt;p&gt;The documentation for &lt;a href=&quot;/out/http/?url=search.cpan.org%2Fdist%2FXML-LibXML%2F&quot;&gt;XML::LibXML&lt;/a&gt; is spread across a number of classes, including:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;/out/http/?url=search.cpan.org%2Fdist%2FXML-LibXML%2Flib%2FXML%2FLibXML%2FParser.pod&quot;&gt;XML::LibXML::Parser&lt;/a&gt; - methods and options for using during parsing&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/out/http/?url=search.cpan.org%2Fdist%2FXML-LibXML%2Flib%2FXML%2FLibXML%2FDocument.pod&quot;&gt;XML::LibXML::Document&lt;/a&gt; - the class returned by the parser&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/out/http/?url=search.cpan.org%2Fdist%2FXML-LibXML%2Flib%2FXML%2FLibXML%2FNode.pod&quot;&gt;XML::LibXML::Node&lt;/a&gt; - abstract base class implementing methods common to different types of DOM nodes&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/out/http/?url=search.cpan.org%2Fdist%2FXML-LibXML%2Flib%2FXML%2FLibXML%2FElement.pod&quot;&gt;XML::LibXML::Element&lt;/a&gt; - methods specific to Element nodes&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/out/http/?url=search.cpan.org%2Fdist%2FXML-LibXML%2Flib%2FXML%2FLibXML%2FAttr.pod&quot;&gt;XML::LibXML::Attr&lt;/a&gt; - methods specific to Attributes nodes&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/out/http/?url=search.cpan.org%2Fdist%2FXML-LibXML%2Flib%2FXML%2FLibXML%2FText.pod&quot;&gt;XML::LibXML::Text&lt;/a&gt; - methods specific to Text nodes&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Zvon.org hosts an &lt;a href=&quot;/out/http/?url=www.zvon.org%2Fxxl%2FXPathTutorial%2FGeneral%2Fexamples.html&quot;&gt;XPath Tutorial&lt;/a&gt; and an interactive &lt;a href=&quot;/out/http/?url=www.zvon.org%3A9001%2Fsaxon%2Fcgi-bin%2FXLab%2FXML%2FxlabIndex.html%3FstylesheetFile%3DXSLT%2FxlabIndex.xslt&quot;&gt;XPath lab&lt;/a&gt;.&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>(P6) Why the tilde makes sense (Juerd)</title>
    <link>http://prlmnks.org/html/490468.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/490468.html</guid>

    <description>
        &lt;p&gt;Before I try to explain why the tilde (&lt;tt&gt;~&lt;/tt&gt;) makes sense, let me first explain what happened to the plus (&lt;tt&gt;+&lt;/tt&gt;).&lt;/p&gt;&lt;p&gt;Infix (in between) plus still adds two numbers: &lt;tt&gt;4 + 5&lt;/tt&gt; will stay &lt;tt&gt;9&lt;/tt&gt;. I think everyone will be very pleased with this. &lt;/p&gt;&lt;p&gt;Prefix (in front) plus changed a little. It used to be a no-op, but in Perl 6 it forces numeric context. In other words, &lt;tt&gt;+$foo&lt;/tt&gt; will evaluate &lt;tt&gt;$foo&lt;/tt&gt; as a number, regardless of what it actually is. This instantly fixes all those ugly occurrences of &lt;tt&gt;$foo + 0&lt;/tt&gt;.&lt;/p&gt;&lt;p&gt;Then, there is the plus in a set of bit operators. As you may or may not know already, the bit operators have all changed. This is done because they&#39;ve found much better uses for the beatiful characters like &lt;tt&gt;|&lt;/tt&gt; and &lt;tt&gt;&amp;amp;&lt;/tt&gt;. In Perl 5, when you had &lt;tt&gt;$foo | $bar&lt;/tt&gt;, it would do a bitwise OR. But it didn&#39;t end there: there are stringy bitwise OR and numeric bitwise OR. The operation chosen would depend on the values of the two variables. This is highly unperlish, because in most other situations we have different operators for strings and numbers, because they just aren&#39;t the same thing.&lt;/p&gt;&lt;p&gt;Thus, numeric OR is now &lt;tt&gt;+|&lt;/tt&gt;. Ugly, yes, but how often do you use these? Besides, it may be ugly, but it&#39;s very clear to anyone who reads the code what &lt;tt&gt;$foo +| $bar&lt;/tt&gt; will do.&lt;/p&gt;&lt;p&gt;By the time you reach this paragraph, you either want to know what tilde has to do with all of this, or you have already thought of it.&lt;/p&gt;&lt;p&gt;Tilde is for strings what plus is for numbers. That is: infix it will add (concatenate), prefix it will force string context (to get rid of &lt;tt&gt;&quot;$foo&quot;&lt;/tt&gt; and &lt;tt&gt;$foo . &quot;&quot;&lt;/tt&gt;. And in bit operators it will give you string bit operations. &lt;/p&gt;&lt;p&gt;Some examples:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;&quot;foo&quot; ~ &quot;bar&quot;   # &gt;&gt;&gt; &quot;foobar&quot;5 ~ 09          # &gt;&gt;&gt; &quot;59&quot;~1e3            # &gt;&gt;&gt; &quot;1000&quot;&quot;ja&quot; ~| &quot;  ph&quot;  # &gt;&gt;&gt; &quot;japh&quot;&lt;/pre&gt;&lt;p&gt;Some want the dot to stay for string concatenation. That would be possible, but the dot as a prefix operator would be troublesome with numbers:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt;&quot;foo&quot; . &quot;bar&quot;   # &gt;&gt;&gt; &quot;foobar&quot;5 . 09          # &gt;&gt;&gt; &quot;59&quot;.1e3            # &gt;&gt;&gt; &quot;1000&quot;&quot;ja&quot; .| &quot;  ph&quot;  # &gt;&gt;&gt; &quot;japh&quot;&lt;/pre&gt;&lt;p&gt;You do want &lt;tt&gt;.1&lt;/tt&gt; to be &lt;tt&gt;0.1&lt;/tt&gt; rather than &lt;tt&gt;&quot;1&quot;&lt;/tt&gt;, I think. And, you may have been used to writing spaces around the dot before, but many people were surprised that while &lt;tt&gt;$foo.$bar&lt;/tt&gt; could result in &lt;tt&gt;&quot;53&quot;&lt;/tt&gt;, &lt;tt&gt;5.3&lt;/tt&gt; never did.&lt;/p&gt;&lt;p&gt;The dot isn&#39;t lost, though. Perl 6 uses it for object orientation, instead of the arrow that Perl 5 used. It can even be used prefix, because method names cannot begin with a digit. Of course, when used without a left side, it defaults to &lt;tt&gt;$_&lt;/tt&gt;. In my code, at least, method calls are used much more often than string concatenation. I like the change because of that, and because of the nice consistency with plus, that tilde can give us.&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>handling multiple file handles for code generation (danmcb)</title>
    <link>http://prlmnks.org/html/489179.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/489179.html</guid>

    <description>
        &lt;p&gt;What follows doesn&#39;t involve a lot of code, but demonstrates some nice things you can do with Perl&#39;s powerful. flexible, concise syntax. It is something I used in a project of mine where I am genearating a lot of C++ code.&lt;/p&gt;&lt;p&gt;The code generates a large number of source and header files. In its first incarnation, each file was just opened and closed as needed, like this:&lt;/p&gt;&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;open SRC &quot;&gt; file&quot;;# print lots of stuffclose SRC;&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;This was fine for a while, but as time went on the thing got slower and slower, as the number of files grew. Also the sounds coming out of the hard disc suggested that some optimisation was in order. Hmm.&lt;/p&gt;&lt;p&gt;So here&#39;s a wish list for some improvements;&lt;ul&gt;&lt;li&gt;keep a number of files open, get back the filehandles as needed by the program by a simple mechanism.&lt;/li&gt;&lt;li&gt;Minimise opening and closing of file handles.&lt;/li&gt;&lt;li&gt;Provide a simple way to print header and footer text in the file (e.g. the guard statements which are necessary in CPP header files).&lt;/li&gt;&lt;li&gt;Clean up nicely when done. This means closing file handles, and calling methods that handle version management software as needed.&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;Here&#39;s how it was done:&lt;/p&gt;&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;{    my %fhs;    sub END    {foreach (keys %fhs){    my $fh = $fhs{$_};    if ($_ =~ /\.h\.new$/)    {print $fh &quot;#endif\n&quot;;    }    close $fh;    if ($_ =~ /\.h\.new$/)    {      Clearcase::handleClearCaseElement($_);    }}    }sub openFile{    my ($file, $header) = @_;        unless (defined $fhs{$file})    {my $f;open ($f, &quot;&gt; $file&quot;) || die &quot;could not open $file for output $!&quot;;$fhs{$file} = $f;print $f $header;    }    return $fhs{$file};}}&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;It&#39;s pretty simple. The END block handles cleanup, adds closing #ENDIFs where necessary, and calls some Clearcase handling routines which take care of version control.. The %fhs hash is private to the END and openFile methods. openFile takes an argument for header info for the file in my system. You could change this around to fit your requirements.&lt;p/&gt;&lt;p&gt;The other code has an easy time now. Whenever a certain file is wanted for output, just call &lt;tt class=&quot;inline_code&quot;&gt;my $fh = openFile(&#39;myFilename.cc&#39;, $header)&lt;/tt&gt; and start printing to $fh. Job done.&lt;/p&gt;&lt;p&gt;The script is back down to a few seconds to run as a result of this (from over 30 seconds) and the disc is a lot happier. The code is much more readable too.&lt;/p&gt;&lt;p&gt;It would be wise, if the number of files gets very high, to extend this code to check that the number of open filehandles does not get too close to the system limit. It&#39;s possible to see some smart mechanism where least used filehandles are closed and only reopened when requested again ... as I don&#39;t need this right now, I&#39;ll leave this as an exercise for some future monk ...&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>How to Ask a Regex Question (with Test::More) (repost, with Sitedocclan approval) (tphyahoo)</title>
    <link>http://prlmnks.org/html/481466.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/481466.html</guid>

    <description>
        This is the second post in the [id://479461] series, and assumes you have read the first, main post. &lt;p&gt;In this installment, we learn how to use Test::More::like($string, $regex) and the qr quotelike operator to ask regex questions in a sane way. Let&#39;s dive right in.&lt;p&gt;******************BEGIN QUESTION TEMPLATE************************&lt;p&gt;O Wise Monks, I can&#39;t get this regex to do what I want it to do. As you can see, it fails two tests. &lt;pre class=&quot;block_code&quot;&gt;use warnings;use strict;use Test::More qw(no_plan);my $emailsregex = qr/\w+@\w+\.(net|com|org)/;while (&lt;DATA&gt;) {like($_, $emailsregex)}__DATA__timmytimmers@aol.comhillary-hillers@aol.comgarbygerbil@herbill.gerbil.orggarbygerbil@herbill.gorgil.orgreginald_reggers@aol.com&lt;/pre&gt;I&#39;m on Windows XP system using the standard ActiveState perl distribution.&lt;p&gt;I got both standard and error output out of my test, into one output file, by running this with &lt;tt class=&quot;inline_code&quot;&gt;emailsregex.pl &gt; output.txt 2&gt;&amp;1 output.txt&lt;/tt&gt;.&lt;p&gt;The output I got was&lt;pre class=&quot;block_code&quot;&gt;ok 1ok 2not ok 3#     Failed test (emailsregex.pl at line 8)#                   &#39;garbygerbil@herbill.gerbil.org# &#39;#     doesn&#39;t match &#39;(?-xism:\w+@\w+\.(net|com|org))&#39;not ok 4#     Failed test (emailsregex.pl at line 8)#                   &#39;garbygerbil@herbill.gorgil.org# &#39;#     doesn&#39;t match &#39;(?-xism:\w+@\w+\.(net|com|org))&#39;ok 51..5# Looks like you failed 2 tests of 5.&lt;/pre&gt;&lt;p&gt;What the heck am I doing wrong?&lt;p&gt;******************END QUESTION TEMPLATE************************&lt;p&gt;(Debugging the regex is left as an exercise for the reader.)
    </description>
</item>

        

<item>
    <title>How to Ask a Question (With Test::More) (repost, now with Sitedocclan approval.) (tphyahoo)</title>
    <link>http://prlmnks.org/html/481465.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/481465.html</guid>

    <description>
        The newbie has questions... the wise old monks have answers... but all too often newbie can&#39;t communicate the question, and the wise old monks fall over each other trying to guess what the newbie might have meant -- perhaps what [merlyn] meant when he wrote &quot;the only personality trait Perl programmers have in common is that they&#39;re all pathologically helpful&quot; (Programming Perl, &quot;Perl Culture&quot;). Examples of this happen all the time -- see for instance the recent post at [id://479266].&lt;p&gt;Well, pathological helpfulness (or xp greed :) ) has its bright side as a cultural feature, but enough is enough. &lt;p&gt;With this series of posts I want to help everyone save time, newbies and wise old owls alike, by providing templates for how to ask certain common types of questions.  This is intended to be an alternative place to point newbies to, rather than the (also very helpful, but in a more general way) [id://172086].&lt;p&gt;As a bonus feature, newbies learning this will also learn Test::More, a powerful tool every monk should incorporate into their life.&lt;p&gt;The first example will be short. My comments are in ~ . Here goes.&lt;p&gt;******************BEGIN QUESTION TEMPLATE************************&lt;p&gt;O Wise Monks, I am having a problem I hope you can help me with. &lt;p&gt;As you can see, in the following code, my zero test for the &quot;multiplies_by_seven&quot; function fails. ~the problem is isolated~&lt;p&gt;I tried googling on &quot;perldoc shift&quot; but no dice. Am I searching with the wrong search terms? ~the newbie tried to help himself first before going to the perlmonks~&lt;p&gt;What the heck am I doing wrong?&lt;p&gt;~The novice now posts his code using code tags: see [Writeup Formatting Tips]~&lt;pre class=&quot;block_code&quot;&gt;# use strict; #~the newbie has used the strictures~use warnings; use Test::More qw(no_plan);my ($result, $expected);# ~convenient way to structure your input and expected output is to ~# ~suck in the test data, which is everything after the __DATA_ line.~while (&lt;DATA&gt;) {#~splits a string on spaces by default; see perldoc -f split~my ($input, $expected) = split; my $output = multiply_by_seven($input);is($output, $expected, &quot;testing $input&quot;);}sub multiply_by_seven {my $number = shift or die &quot;no number&quot;;return $number*7;} #~convenient way to structure your input and expected output, #assuming that you can use whitespace as the delimiter.__DATA__1 72 143 210 0&lt;/pre&gt;I&#39;m on Windows XP system using the standard ActiveState perl distribution. ~The novice mentions what system he is on.~&lt;p&gt;I got both standard and error output out of my test, into one output file, by running this with &lt;tt class=&quot;inline_code&quot;&gt;perl multiplyBySeven.pl &gt; output.txt 2&gt;&amp;1 output.txt&lt;/tt&gt;. ~Enables newbie to communicate his test result with a minimum of putzing around~&lt;p&gt;The output is:&lt;pre class=&quot;block_code&quot;&gt;ok 1 - testing 1ok 2 - testing 2ok 3 - testing 3no number at multiplyBySeven.pl line 18, &lt;DATA&gt; line 4.1..3# Looks like your test died just after 3.&lt;/pre&gt;&lt;p&gt;Any ideas? Thanks very much in advance, o wise monks :)&lt;p&gt;******************END QUESTION TEMPLATE************************&lt;p&gt;That&#39;s basically it. Why the 0 test fails is left as an exercise for the reader :)&lt;P&gt;Soon to come: &lt;p&gt;How To Ask a Regex Question (with Test::More)&lt;br&gt;How To Ask a Multiline Regex Question (with Test::More)&lt;br&gt;How To Ask a Data Structures Question (with Test::More)&lt;br&gt;
    </description>
</item>

        

<item>
    <title>How to Ask A Regex Question (With Test::More) (tphyahoo)</title>
    <link>http://prlmnks.org/html/479480.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/479480.html</guid>

    <description>
        This is the second post in the [id://479461] series, and assumes you have read the first, main post. &lt;p&gt;In this installment, we learn how to use Test::More::like($string, $regex) and the qr quotelike operator to ask regex questions in a sane way. Let&#39;s dive right in.&lt;p&gt;******************BEGIN QUESTION TEMPLATE************************&lt;p&gt;O Wise Monks, I can&#39;t get this regex to do what I want it to do. As you can see, it fails two tests. &lt;pre class=&quot;block_code&quot;&gt;use warnings;use strict;use Test::More qw(no_plan);my $emailsregex = qr/\w+@\w+\.(net|com|org)/;while (&lt;DATA&gt;) {like($_, $emailsregex)}__DATA__timmytimmers@aol.comhillary-hillers@aol.comgarbygerbil@herbill.gerbil.orggarbygerbil@herbill.gorgil.orgreginald_reggers@aol.com&lt;/pre&gt;I&#39;m on Windows XP system using the standard ActiveState perl distribution.&lt;p&gt;I got both standard and error output out of my test, into one output file, by running this with &lt;tt class=&quot;inline_code&quot;&gt;emailsregex.pl &gt; output.txt 2&gt;&amp;1 output.txt&lt;/tt&gt;.&lt;p&gt;The output I got was&lt;pre class=&quot;block_code&quot;&gt;ok 1ok 2not ok 3#     Failed test (emailsregex.pl at line 8)#                   &#39;garbygerbil@herbill.gerbil.org# &#39;#     doesn&#39;t match &#39;(?-xism:\w+@\w+\.(net|com|org))&#39;not ok 4#     Failed test (emailsregex.pl at line 8)#                   &#39;garbygerbil@herbill.gorgil.org# &#39;#     doesn&#39;t match &#39;(?-xism:\w+@\w+\.(net|com|org))&#39;ok 51..5# Looks like you failed 2 tests of 5.&lt;/pre&gt;&lt;p&gt;What the heck am I doing wrong?&lt;p&gt;******************END QUESTION TEMPLATE************************&lt;p&gt;(Debugging the regex is left as an exercise for the reader.)
    </description>
</item>

        

<item>
    <title>How To Ask a Question (With Test::More) (tphyahoo)</title>
    <link>http://prlmnks.org/html/479461.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/479461.html</guid>

    <description>
        The newbie has questions... the wise old monks have answers... but all too often newbie can&#39;t communicate the question, and the wise old monks fall over each other trying to guess what the newbie might have meant -- perhaps what [merlyn] meant when he wrote &quot;the only personality trait Perl programmers have in common is that they&#39;re all pathologically helpful&quot; (Programming Perl, &quot;Perl Culture&quot;). Examples of this happen all the time -- see for instance the recent post at [id://479266].&lt;p&gt;Well, pathological helpfulness (or xp greed :) ) has its bright side as a cultural feature, but enough is enough. &lt;p&gt;With this series of posts I want to help everyone save time, newbies and wise old owls alike, by providing templates for how to ask certain common types of questions.  This is intended to be an alternative place to point newbies to, rather than the (also very helpful, but in a more general way) [id://172086].&lt;p&gt;As a bonus feature, newbies learning this will also learn Test::More, a powerful tool every monk should incorporate into their life.&lt;p&gt;The first example will be short. My comments are in ~ . Here goes.&lt;p&gt;******************BEGIN QUESTION TEMPLATE************************&lt;p&gt;O Wise Monks, I am having a problem I hope you can help me with. &lt;p&gt;As you can see, in the following code, my zero test for the &quot;multiplies_by_seven&quot; function fails. ~the problem is isolated~&lt;p&gt;I tried googling on &quot;perldoc shift&quot; but no dice. Am I searching with the wrong search terms? ~the newbie tried to help himself first before going to the perlmonks~&lt;p&gt;What the heck am I doing wrong?&lt;p&gt;~The novice now posts his code using code tags: see [Writeup Formatting Tips]~&lt;pre class=&quot;block_code&quot;&gt;# use strict; #~the newbie has used the strictures~use warnings; use Test::More qw(no_plan);my ($result, $expected);# ~convenient way to structure your input and expected output is to ~# ~suck in the test data, which is everything after the __DATA_ line.~while (&lt;DATA&gt;) {#~splits a string on spaces by default; see perldoc -f split~my ($input, $expected) = split; my $output = multiply_by_seven($input);is($output, $expected, &quot;failed for $input&quot;);}sub multiply_by_seven {my $number = shift or die &quot;no number&quot;;return $number*7;} #~convenient way to structure your input and expected output, #assuming that you can use whitespace as the delimiter.__DATA__1 72 143 210 0&lt;/pre&gt;I&#39;m on Windows XP system using the standard ActiveState perl distribution. ~The novice mentions what system he is on.~&lt;p&gt;I got both standard and error output out of my test, into one output file, by running this with &lt;tt class=&quot;inline_code&quot;&gt;perl multiplyBySeven.pl &gt; output.txt 2&gt;&amp;1 output.txt&lt;/tt&gt;. ~Enables newbie to communicate his test result with a minimum of putzing around~&lt;p&gt;The output is:&lt;pre class=&quot;block_code&quot;&gt;ok 1 - failed for 1ok 2 - failed for 2ok 3 - failed for 3no number at multiplyBySeven.pl line 16, &lt;DATA&gt; line 4.1..3# Looks like your test died just after 3.&lt;/pre&gt;&lt;p&gt;Any ideas? Thanks very much in advance, o wise monks :)&lt;p&gt;******************END QUESTION TEMPLATE************************&lt;p&gt;That&#39;s basically it. Why the 0 test fails is left as an exercise for the reader :)&lt;P&gt;Soon to come: &lt;p&gt;How To Ask a Regex Question (with Test::More)&lt;br&gt;How To Ask a Multiline Regex Question (with Test::More)&lt;br&gt;How To Ask a Data Structures Question (with Test::More)&lt;br&gt;
    </description>
</item>

        

<item>
    <title>The extremely simple buffering tutorial (really just an example) (tphyahoo)</title>
    <link>http://prlmnks.org/html/476757.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/476757.html</guid>

    <description>
        Only for novice monks too lazy to read [dominus]&#39;s &lt;a href=&quot; http://perl.plover.com/FAQs/Buffering.html&quot;&gt;suffering from buffering&lt;/a&gt;:&lt;p&gt;from [perlvar]:&lt;pre class=&quot;block_code&quot;&gt;HANDLE-&gt;autoflush(EXPR)$OUTPUT_AUTOFLUSH # need to use English at the start of your module $|    If set to nonzero, forces a flush right away and after every write or print on the currently selected output channel. Default is 0 (regardless of whether the channel is really buffered by the system or not; $| tells you only whether you&#39;ve asked Perl explicitly to flush after each write). STDOUT will typically be line buffered if output is to the terminal and block buffered otherwise. Setting this variable is useful primarily when you are outputting to a pipe or socket, such as when you are running a Perl program under rsh and want to see the output as it&#39;s happening. This has no effect on input buffering. See getc in the perlfunc manpage for that. (Mnemonic: when you want your pipes to be piping hot.)&lt;/pre&gt;Some simple code:&lt;pre class=&quot;block_code&quot;&gt;#see also http://perl.plover.com/FAQs/Buffering.htmluse strict;use warnings;#prints, waits a second, printsfor (1..3) {sleep 1;print &quot;$_\n&quot;;}#without the newline, waits the entire time and then prints the whole thing.for (1..3) {sleep 1;print &quot;$_&quot;;}$| = 1;#now it worksfor (1..3) {sleep 1;print &quot;$_&quot;;}#you might want to go back to the default behavior now.$| = 0;&lt;/pre&gt;
    </description>
</item>

        

<item>
    <title>Not Exactly a Hash Tutorial (planetscape)</title>
    <link>http://prlmnks.org/html/471590.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/471590.html</guid>

    <description>
        &lt;h4&gt;(A List of Resources, Definitely A Work in Progress,&amp;nbsp; and Contributions Always Welcome :-)&lt;/h4&gt;&lt;h5&gt;Online:&lt;/h5&gt;&lt;blockquote&gt;  &lt;p&gt;&lt;a href=&quot;http://learn.perl.org/library/beginning_perl/3145_Chap03.pdf&quot;&gt;  Chapter 3&lt;/a&gt; in &lt;a href=&quot;http://learn.perl.org/library/beginning_perl/&quot;&gt;  &lt;i&gt;Beginning Perl&lt;/i&gt;&lt;/a&gt; by Simon Cozens&lt;/p&gt;  &lt;p&gt;Chapter 5 of &lt;a href=&quot;http://ebb.org/PickingUpPerl/pickingUpPerl.pdf&quot;&gt;&lt;i&gt;  Picking Up Perl&lt;/i&gt;&lt;/a&gt; by &lt;a href=&quot;http://www.ebb.org/bkuhn&quot;&gt;Bradley M. Kuhn&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Section 2.3 in &lt;i&gt;&lt;a href=&quot;http://www.greglondon.com/iperl/pdf/iperl.pdf&quot;&gt;  Impatient Perl&lt;/a&gt; &lt;/i&gt;by &lt;font face=&quot;Times, serif&quot;&gt;  &lt;a href=&quot;http://www.greglondon.com/&quot;&gt;Greg London&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://www.5sigma.com/perl/effective_perl.pdf&quot;&gt;Effective Perl:   Intermediate and Advanced Topics&lt;/a&gt; contains a wealth of information, not   limited to hashes, but also including several pages on  &lt;a href=&quot;http://web.archive.org/web/20031011161713/http://www.effectiveperl.com/pegs/&quot;&gt;  Joseph N. Hall&#39;s PErl Graphical Structures (PEGS)&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://www.sysarch.com/perl/autoviv.txt&quot;&gt;Uri Guttman&#39;s tutorial on   AUTOVIVIFICATION&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/out/node/tlm&quot;&gt;tlm&lt;/a&gt;&#39;s &lt;a href=&quot;/html/445927.html&quot;&gt;rant&lt;/a&gt; on AUTOVIVIFICATION&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/out/id/87227&quot;&gt;Extracting array of hashes from data&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/out/google/perl hash tutorial&quot;&gt;Obligatory Google&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/blockquote&gt;&lt;h5&gt;Print:&lt;/h5&gt;&lt;blockquote&gt;  &lt;p&gt;Chapter 5 of &lt;i&gt;&lt;a href=&quot;http://www.oreilly.com/catalog/lperl3/index.html&quot;&gt;  Learning Perl&lt;/a&gt;&lt;/i&gt; by Randal L. Schwartz and Tom Phoenix&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;font color=&quot;#0080ff&quot;&gt;p&lt;/font&gt;  &lt;font color=&quot;#008bf3&quot;&gt;&amp;#108;&lt;/font&gt;  &lt;font color=&quot;#0097e7&quot;&gt;&amp;#97;&lt;/font&gt;  &lt;font color=&quot;#00a2dc&quot;&gt;n&lt;/font&gt; &lt;font color=&quot;#00aed0&quot;&gt;&amp;#101;&lt;/font&gt;  &lt;font color=&quot;#00b9c5&quot;&gt;t&lt;/font&gt;  &lt;font color=&quot;#00c5b9&quot;&gt;s&lt;/font&gt;  &lt;font color=&quot;#00d0ae&quot;&gt;c&lt;/font&gt;  &lt;font color=&quot;#00dca2&quot;&gt;a&lt;/font&gt;  &lt;font color=&quot;#00e797&quot;&gt;&amp;#112;&lt;/font&gt;  &lt;font color=&quot;#00f38b&quot;&gt;e&lt;/font&gt; &lt;/p&gt;
    </description>
</item>

        

<item>
    <title>PDF::API2 Table (Sapphira)</title>
    <link>http://prlmnks.org/html/458201.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/458201.html</guid>

    <description>
        Hi,&lt;br&gt;&lt;br&gt;do anybody know: &lt;br&gt;how can i create a table with the modul (PDF::API2)? &lt;br&gt;And how can i make that automatically is word-wrapping at the end of the row?&lt;br&gt;&lt;br&gt;Thanks&lt;br&gt;Sapphira
    </description>
</item>

        

<item>
    <title>Understanding transformation sorts (ST, GRT), the details (5mi11er)</title>
    <link>http://prlmnks.org/html/457993.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/457993.html</guid>

    <description>
        Let me start by saying that while I understood in theory what was happening in the Schwartzian and Guttman Rosler Transformations, I had a difficult time understanding the the details of how the magic &quot;map sort map&quot; incantations actually worked.&lt;p&gt;I had read the requisite articles scattered around the Monastery, especially [id://145659|Advanced Sorting - GRT - Guttman Rosler Transform] and [id://447633|Choosing the right sort (Or: WUDsamatter?)] and [id://287149|fast, flexible, stable sort]. From [id://22609|tye&#39;s] reputation, and his description in this last node, I&#39;d figured he touched upon something brilliant, but I certainly didn&#39;t &quot;get it&quot;.&lt;p&gt;I copied the snippet, filled in the XFORM function, and ran the code manually through the debugger printing what various parts of the sort transformation did, and finally &quot;got it&quot;.&lt;p&gt;Now, I&#39;m pretty intelligent, so I figured that if I hadn&#39;t gotten it after reading bunches of the &quot;sort&quot; technique articles around the catacombs, that it would probably help a number of others if I could explain the magic a bit so they might understand what was going on with these transformation techniques.&lt;p&gt;&lt;h3&gt;The basic theory&lt;/h3&gt;We take the data we want to sort some particular way, and figure out how to mangle that data such that a standard Perl ascii sort will do the job for us, then unmangle the data such that we get back our original information, except now in sorted order. If you understand this, and have inklings about how to transform the data, but don&#39;t understand the details about how it all gets put together, this node is intended specifically for you.&lt;p&gt;&lt;h3&gt;How this Transformation works&lt;/h3&gt;As is true for all transformations, it helps a great deal to first understand that everything within this construct: (directly from [id://287149|Tye&#39;s node] above)&lt;pre class=&quot;block_code&quot;&gt;my @sorted= @list[    map { unpack &quot;N&quot;, substr($_,-4) }    sort    map { XFORM($list[$_]) . pack &quot;N&quot;, $_ }    0..$#list];&lt;/pre&gt; is layed out in reverse order from which the execution is done.  So, start at the end, you&#39;ll see the 0..$#list, which is just a list of all the indexes within the array @list.  The indexes are what we&#39;re iterating over, and $_ is set to each index in turn.&lt;p&gt;Next we have :&lt;tt class=&quot;inline_code&quot;&gt;map { XFORM($list[$_]) . pack &quot;N&quot;, $_ }&lt;/tt&gt; which simply calls XFORM(), which is your transformation of the data into a sortable string, and then &lt;b&gt;appends&lt;/b&gt; to that string an &lt;b&gt;encoding&lt;/b&gt; of the index value packed (in an architecturally independant format) into 4 bytes. That&#39;s the &lt;tt class=&quot;inline_code&quot;&gt;pack &quot;N&quot;, $_ &lt;/tt&gt; portion. The map statement just says to do that for every index.&lt;p&gt;The resulting array of transformed, stringified data with the index values packed and glued to the end of each string is then passed to the sort routine. Assuming your transformation works as it is supposed to, the correctly sorted array of transformed, stringified data is then passed to the first map statement. This map just grabs the last 4 bytes of each string, which must be our encoded index value from the original array, and decodes it back into a usable index value; and it does this for all the entries. To be completely clear, the transformed, stringified stuff is thrown away at this point; only the index values are left.&lt;p&gt;What we have at this point is an array of index values from the original array, but these index values are in the desired sorted order!  At this point we&#39;ve simplified the original transformation into this: &lt;tt class=&quot;inline_code&quot;&gt;my @sorted=@list[@array_of_sorted_indexes];&lt;/tt&gt; Execute that and we finally get @sorted which has the original array&#39;s information, but in sorted order, and @list is unmodified.&lt;p&gt;If you&#39;re fuzzy about the @list&amp;#91;@array&amp;#93; notation, this is perfectly legal. Try this in a debugging session:&lt;br&gt;&lt;tt class=&quot;inline_code&quot;&gt;print @{[a..z]}[0,4,8,14,20];&lt;/tt&gt; and you&#39;ll get the list &#39;a,e,i,o,u&#39; back.&lt;p&gt;If all that was still not clear enough and you need a concrete example with the sort magic broken out into individual statements, the following sorts dotted IP address information:&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perluse strict;use warnings;sub XFORM {    # Extract the sort key from $_[0] and return it.    # This will often be written in-line    # rather than as a real subroutine.    return sprintf(&quot;%012.0f&quot;, ip2val($_[0]));}my ($addstr,$value,@addstrary,@addvalary,@sorted,$DEBUG);{     no warnings &#39;numeric&#39;;    if($ARGV[0] &gt; 0) {        $DEBUG = shift @ARGV;    } else {        $DEBUG = 0;    }}while (&lt;&gt;) {    s/(^\s+)//;        #remove indentation    s/\s+[\n\r]+//g;   #remove all eol spaces/tabs &amp; ctrl chars    if(/^$/) { next; } #ignore blank lines    if(/^#/) { next; } #ignore comments    ($addstr) = Extract_IP_Address($_);    if($addstr ne &#39;&#39;) {        #Use this to check the XFORM routine        #printf &quot;%15.15s   %s\n&quot;,$addstr,XFORM($addstr);        push @addstrary, $addstr;    }}if($DEBUG == 0) {    @sorted= @addstrary[         map { unpack &quot;N&quot;, substr($_,-4) }         sort         map { XFORM($addstrary[$_]) . pack &quot;N&quot;, $_ }         0..$#addstrary    ];} else {    #split up Tye&#39;s GRT sort above into separate pieces    my (@arytosort, @sorted_stuff, @index_info);    @arytosort = map { XFORM($addstrary[$_]) . pack &quot;N&quot;, $_ } 0..$#addstrary;    @sorted_stuff = sort @arytosort;    @index_info = map { unpack &quot;N&quot;, substr($_,-4) } @sorted_stuff;    @sorted = @addstrary[@index_info];}foreach my $str (@sorted) {    print &quot;$str\n&quot;;}#---- Misc. IP address routines ----############################################ convert 4 byte integer value to an IP address###########################################sub val2ip {    my ($a,$b,$c,$d)=unpack(&quot;CCCC&quot;,pack(&quot;N&quot;,$_[0]));    return &quot;$a.$b.$c.$d&quot;;}############################################ convert IP address to a 4 byte integer value###########################################sub ip2val {    if ( $_[0]=~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/o ){        return (unpack(&quot;N&quot;,pack(&quot;CCCC&quot;,$1,$2,$3,$4)) );    } else {        return 0;    }}###################################################################### Find the first dotted ip address in any string, puts it in $1, # and put the individual octets in $2, $3, $4 &amp; $5. Figure out the# long integer representation of that address, and Return everything# in a list.## NOTE: it doesn&#39;t check to make sure each octet is between 0-254, #   nor if the numbers between the dots are 1 to 3 characters in length.## Example: given &quot;the IP address of www.xxx.com is 206.24.105.142&quot;# return the list (&#39;206.24.105.142&#39;,206,24,105,142,3457706382)#####################################################################sub Extract_IP_Address {    if ( $_[0]=~ /(([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+))/o ){        return ($1,$2,$3,$4,$5, unpack(&quot;N&quot;,pack(&quot;CCCC&quot;,$2,$3,$4,$5)) );    } else {        return ();    }}&lt;/pre&gt;It&#39;ll read from an input file or Standard In, and grab the first IP address on each line.  If you want to manually run through the split up sort steps within a debugger, the script&#39;s first argument should be any positive number.  Or just set $DEBUG yourself while in the debugger...&lt;p&gt;-Scott
    </description>
</item>

        

<item>
    <title>Implementing Dispatch Tables (Roy Johnson)</title>
    <link>http://prlmnks.org/html/456530.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/456530.html</guid>

    <description>
        A dispatch table is just a mapping from strings to actions.If you find yourself lamenting the lack of a C-style switch/case statementin Perl, &lt;em&gt;and&lt;/em&gt; you find yourself grumbling that the equivalentseries of if statements is a linear search, you probably want adispatch table. In Perl, the hash is a natural way to implement this.&lt;p&gt;There is an [http://search.cpan.org/~pardus/Zoidberg-0.95/lib/Zoidberg/DispatchTable.pm|implementation in CPAN], but I don&#39;t think it&#39;s what we&#39;relooking for. It&#39;s certainly not straightforward, and dispatch tables are easy enough to roll your own.&lt;h3&gt;The trivial case&lt;/h3&gt;A basic dispatch table might look like this:&lt;pre class=&quot;block_code&quot;&gt;my %disp_table = ( something =&gt; \&amp;do_something );&lt;/pre&gt;You put a string in, you get a code ref out. Then, presumably, you executethe code ref:&lt;pre class=&quot;block_code&quot;&gt;$disp_table{&#39;something&#39;}();&lt;/pre&gt;What could be simpler?&lt;h3&gt;Defaulting&lt;/h3&gt;That&#39;s great if what you&#39;re looking for is in the table, but if it&#39;snot, you&#39;re going to get an error for trying to use an empty string asa subroutine ref, because the hash value came up &lt;tt class=&quot;inline_code&quot;&gt;undef&lt;/tt&gt;. Soyou need to have an alternative:&lt;pre class=&quot;block_code&quot;&gt;($disp_table{&#39;not there&#39;} || sub {})();&lt;/pre&gt;Now if the hash lookup returns nothing, you fall back on a subroutinethat doesn&#39;t do anything. Of course, you could use a default that didsomething if you wanted to.&lt;h3&gt;Fall-through (chaining)&lt;/h3&gt;What if you&#39;ve got a bunch of things that map to the same action? You couldduplicate your code for each of them:&lt;pre class=&quot;block_code&quot;&gt;    one   =&gt; sub { print &quot;Number!\n&quot; },    two   =&gt; sub { print &quot;Number!\n&quot; },    three =&gt; sub { print &quot;Number!\n&quot; },&lt;/pre&gt;which should then raise a red flag that you need to abstract it outinto its own subroutine. And if &#39;one&#39; is supposed to do somethingbefore falling through, you can embed that sub call in its custom action:&lt;pre class=&quot;block_code&quot;&gt;    one   =&gt; sub { print &quot;The loneliest &quot;; number() },    two   =&gt; \&amp;number,    three =&gt; \&amp;number,&lt;/pre&gt;By chaining calls this way, you can make things &quot;fall through&quot; to whatever you want them to. They are not limited by what comes next (which is good, because ina hash, what comes next is unpredictable).&lt;h3&gt;Matching patterns and ranges&lt;/h3&gt;Up until a few minutes ago, I would have said that using a dispatch tableprecludes pattern matching. I would have been wrong. Super Search on dispatchtable came up with [429761|an ingenious post by grinder] that shows how todo just that, using[http://search.cpan.org/~dland/Regexp-Assemble-0.15/Assemble.pm|Regexp::Assemble]. In a sense, the pattern match is still searching all the alternatives,albeit in an optimized way. However, the circumstances in which a dispatchtable is most advantageous &amp;mdash; where you have a very large number ofalternatives &amp;mdash; are where a regex is likely to bog down.&lt;p&gt;Ranges offer a similar challenge. Of course, neither patterns nor ranges arehandled by C&#39;s switch statement. Modula handles ranges, but it sacrifices fall-through (and may only work on numbers and single characters). You can&#39;t have everything. If you can&#39;t enumerate all the cases you want to cover, youdon&#39;t want a dispatch table. Functions that check all the alternativesin order (such as my [444780|smatch]) can offer a great deal of flexibility.&lt;h3&gt;Having Perl build the table&lt;/h3&gt;The only really tricky bit about having a subroutine that translates alist of arguments resembling a C switch statement into a dispatch tableis in implementing fall-through. A program doesn&#39;t have the luxury ofcreating new named subroutines, so there&#39;s a bit of bookkeepingto handle there.&lt;p&gt;I have implemented a function that does the translation for all thefeatures described above (except patterns and ranges, for the reasons cited)in the Snippet [id://456132].
    </description>
</item>

        

<item>
    <title>vdd (NodeReaper)</title>
    <link>http://prlmnks.org/html/453961.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/453961.html</guid>

    <description>
        This node was taken out by the &lt;a href=&quot;/out/node/NodeReaper&quot;&gt;NodeReaper&lt;/a&gt; on Wed May  4 10:28:36 2005 (EST)&lt;BR&gt;Reason:  &amp;#91;&lt;a href=&quot;/out/node/gellyfish&quot;&gt;gellyfish&lt;/a&gt;]: delete&lt;P&gt;For more information on this node visit:  &lt;A HREF=&quot;?nodenum=453961;node=Visit%20Reaped%20Nodes&quot;&gt;this&lt;/A&gt;
    </description>
</item>

        

<item>
    <title>How To: Make An Iterator (Limbic~Region)</title>
    <link>http://prlmnks.org/html/451278.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/451278.html</guid>

    <description>
        &lt;h2&gt;Purpose:&lt;/h2&gt;The purpose of this tutorial is to give a general overview of what an iterator is, why they are useful, and how to build one.  It is intended to give the reader enough information to begin using iterators though a certain level of understanding is assumed.  The &lt;a href=&quot;?node_id=954#see_also&quot;&gt;See Also&lt;/a&gt; section should be researched if supplemental information is needed.&lt;READMORE&gt;&lt;h2&gt;What Is An Iterator&lt;/h2&gt;An iterator is simply a code reference that when executed will calculate the next item in a list and return it.  In the event the list is exhausted, an agreed upon return value is given.  A reusable iterator will have a constructing subroutine that creates a closure around any necessary state variables and returns an anonymous code ref that will be used as the iterator.&lt;h2&gt;Why Are Iterators Useful&lt;/h2&gt;Typically, the most straightforward to get a list is to define an algorithm to generate the list and store the results in an array.  There are several reasons why you might want to consider an iterator instead:&lt;ul&gt;&lt;li&gt;list is too long to fit into memory&lt;/li&gt;Since only the state information necessary to calculate the next item is stored, the iterator typically has a tiny memory footprint.&lt;li&gt;infinite list (also referred to as a stream)&lt;/li&gt;Iterators are probably the only way to represent infinite lists.&lt;li&gt;Circular list&lt;/li&gt;While the list may be finite, you want the traversal of the list to be infinite (imagine days of the week).&lt;li&gt;Unknown number of items needed&lt;/li&gt;It is a waste to create a list with hundreds of thousands of items if you find what you are looking for at number 42.&lt;li&gt;Need multiple copies of the list&lt;/li&gt;Each instance of an iterator has a copy of its own state variables via the closure and since the anonymous code reference is relatively light-weight, it is efficient to pass around.&lt;/ul&gt;&lt;h2&gt;How To Build An Iterator&lt;/h2&gt;The basic structure of an iterator constructor looks like:&lt;pre class=&quot;block_code&quot;&gt;sub gen_iterator {    my @initial_conditions = @_;    my $current_state;    return sub {        # ... code to calculate $next_state;        return $current_state = $next_state;       };}&lt;/pre&gt;If anything needs to be known before work can begin, initial conditions are passed in as arguments.  Any state variables that are needed to calculate are declared and/or initialized at the same level as the anonymous sub routine.  A block of code that interacts with the state variables is returned to the caller completing the transaction.  Each time the code reference is executed, the state variables are updated and the next item is returned.&lt;pre class=&quot;block_code&quot;&gt;my $next = gen_iterator( 42 );print $next-&gt;(), &quot;\n&quot; for 1..10;  # next 10 items in list&lt;/pre&gt;&lt;h4&gt;Example:  list is too long for memory&lt;/h4&gt;&lt;pre class=&quot;block_code&quot;&gt;my @list = map { my @lines = &lt;$_&gt;; \@lines } @f_handles;# becomesmy $next = gen_iterator( \@f_handles );while ( my $lines = $next-&gt;() ) {    print @$lines, &quot;\n&quot;;}sub gen_iterator {    my $f_handle = shift;    my $index = -1;    return sub {        $index++;                 return undef if $index &gt; $#f_handle;        my @lines = &lt;$f_handle-&gt;[$index]&gt;;        return \@lines;    };}&lt;/pre&gt;&lt;h4&gt;Example:  infinite list&lt;/h4&gt;&lt;pre class=&quot;block_code&quot;&gt;sub gen_iterator {    my $curr = shift;    $curr++ if $curr % 2;    my $next;    return sub {        if ( ! defined $next ) { return $next = $curr }        return $next += 2;    };}my $next_even = gen_iterator( 41 );print $next_even-&gt;(), &quot;\n&quot; while 1;&lt;/pre&gt;&lt;h4&gt;Example:  circular list&lt;/h4&gt;&lt;pre class=&quot;block_code&quot;&gt;sub gen_iterator {    my @list = @_;    my $index = -1;    return sub {        $index++;        $index = 0 if $index &gt; $#list;        return $list[ $index ];    };}my $work_day = gen_iterator( qw/Mon Tue Wed Thu Fri/ );print $work_day-&gt;(), &quot;\n&quot; for 1..7;&lt;/pre&gt;&lt;h4&gt;Example:  unknown number of items needed&lt;/h4&gt;&lt;pre class=&quot;block_code&quot;&gt;sub gen_iterator {    my $prime;    return sub {        # ... code to calculate $next_prime from $prime;        return $prime = $next_prime;       };}my $next_prime = gen_iterator();while ( 1 ) {    my $p = $next_prime-&gt;();    last if crack_code( $p );}&lt;/pre&gt;&lt;h4&gt;Example:  multiple copies needed&lt;/h4&gt;Left as an exercise for the reader.&lt;h2&gt;Things To Consider&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;What to use to indicate list is exhausted&lt;/li&gt;Be sure to document what value indicates the end of the list and be sure to use something that isn&#39;t considered a valid item in the list.  If it is impossible to know, give the user the ability to specify what value to use as part of the initial conditions passed to the constructor&lt;li&gt;Using references to external variables as state variables&lt;/li&gt;In the first example, instead of making a copy of @f_handles, a reference was used.  Changes to @f_handles may have side-effects during the course of iteration.  Always document assumptions.&lt;li&gt;Special return conditions may apply&lt;/li&gt;In order to avoid skipping the initial condition in the list, a special return clause was used.  Often this is only needed for the first item.&lt;li&gt;State variable persistence&lt;/li&gt;Just because the iterator has reached the end of the list doesn&#39;t mean it magically goes away.  The state variables still have references to them so they are not garbage collected.  If you have a substantial amount of state variables, either take special steps to destroy them at the end of the list or be sure to document them so people using your code can destroy the iterator itself at the calling level.&lt;/ul&gt;&lt;a name=&quot;see_also&quot;&gt;&lt;h2&gt;See Also&lt;/h2&gt;&lt;/a&gt;&lt;ul&gt;&lt;li&gt;[id://268891] by [broquaint]&lt;/li&gt;&lt;li&gt;[doc://perlsub] (&lt;i&gt;perldoc perlsub&lt;/i&gt;)&lt;/li&gt;&lt;li&gt;[http://perl.plover.com/hop/|Higher Order Perl] by [Dominus]&lt;/li&gt;A great book that covers the concept of iterators and a whole lot more&lt;/ul&gt;&lt;/READMORE&gt;&lt;p&gt;Cheers - [Limbic~Region|L~R]&lt;/p&gt;&lt;small&gt;Note:  The examples in this tutorial are meant for instructional purposes and are not guaranteed to be complete or functional without work from the user.&lt;/small&gt;
    </description>
</item>

        

<item>
    <title>Jos&#39;s Guide for creating Perl modules (cog)</title>
    <link>http://prlmnks.org/html/431702.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/431702.html</guid>

    <description>
        &lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#name&quot;&gt;NAME&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#synopsis&quot;&gt;SYNOPSIS&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#description&quot;&gt;DESCRIPTION&lt;/a&gt;&lt;/li&gt;    &lt;ul&gt;    &lt;li&gt;&lt;a href=&quot;#before_you_start&quot;&gt;Before you start&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;#picking_a_good&quot;&gt;Picking a good name for your module&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;#start_your_module&quot;&gt;Start your module&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;#h2xs&quot;&gt;h2xs&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;#module-starter&quot;&gt;module-starter&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;#extutils&quot;&gt;ExtUtils::ModuleMaker&lt;/a&gt;&lt;/li&gt;    &lt;/ul&gt;&lt;li&gt;&lt;a href=&quot;#step_by_step&quot;&gt;Step by step: what to do&lt;/a&gt;&lt;/li&gt;    &lt;ul&gt;    &lt;li&gt;&lt;a href=&quot;#document_first&quot;&gt;Document first&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;#create_tests&quot;&gt;Create tests&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;#use_strict&quot;&gt;Use strict&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;#use_warnings&quot;&gt;Use warnings&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;#exports&quot;&gt;Exports&lt;/a&gt;&lt;/li&gt;        &lt;ul&gt;        &lt;li&gt;&lt;a href=&quot;#how_it_works&quot;&gt;How it works&lt;/a&gt;&lt;/li&gt;        &lt;li&gt;&lt;a href=&quot;#what_to_export&quot;&gt;What to export&lt;/a&gt;&lt;/li&gt;        &lt;/ul&gt;    &lt;li&gt;&lt;a href=&quot;#inside_your_distribution&quot;&gt;Inside your distribution&lt;/a&gt;&lt;/li&gt;        &lt;ul&gt;        &lt;li&gt;&lt;a href=&quot;#keep_the_changes&quot;&gt;Keep the Changes up to date&lt;/a&gt;&lt;/li&gt;        &lt;li&gt;&lt;a href=&quot;#don_t_forget_the_readme&quot;&gt;Don&#39;t forget the README&lt;/a&gt;&lt;/li&gt;        &lt;li&gt;&lt;a href=&quot;#the_manifest&quot;&gt;The MANIFEST&lt;/a&gt;&lt;/li&gt;        &lt;li&gt;&lt;a href=&quot;#makefile_pl&quot;&gt;Makefile.PL&lt;/a&gt;&lt;/li&gt;        &lt;li&gt;&lt;a href=&quot;#version_numbers&quot;&gt;Version numbers&lt;/a&gt;&lt;/li&gt;        &lt;/ul&gt;    &lt;li&gt;&lt;a href=&quot;#almost_done&quot;&gt;Almost done&lt;/a&gt;&lt;/li&gt;        &lt;ul&gt;        &lt;li&gt;&lt;a href=&quot;#test_it_yourself&quot;&gt;Test it yourself&lt;/a&gt;&lt;/li&gt;        &lt;/ul&gt;    &lt;li&gt;&lt;a href=&quot;#before_uploading&quot;&gt;Before uploading&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;#uploading&quot;&gt;Uploading&lt;/a&gt;&lt;/li&gt;    &lt;/ul&gt;&lt;li&gt;&lt;a href=&quot;#other_good_practices&quot;&gt;Other good practices&lt;/a&gt;&lt;/li&gt;    &lt;ul&gt;    &lt;li&gt;&lt;a href=&quot;#release_early_release_often&quot;&gt;Release early, release often&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;#good_style&quot;&gt;Good style&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;#source_control&quot;&gt;Source control&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;#me_got_kwalitee&quot;&gt;Me got Kwalitee&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;#other_things_you_should_know&quot;&gt;Other things you should know&lt;/a&gt;&lt;/li&gt;        &lt;ul&gt;        &lt;li&gt;&lt;a href=&quot;#cpan_testers&quot;&gt;CPAN Testers&lt;/a&gt;&lt;/li&gt;        &lt;li&gt;&lt;a href=&quot;#registering_modules&quot;&gt;Registering modules&lt;/a&gt;&lt;/li&gt;        &lt;/ul&gt;    &lt;/ul&gt;&lt;li&gt;&lt;a href=&quot;#so_i_have_a_module&quot;&gt;So I have a module. Now what?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#final_words&quot;&gt;Final words&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#see_also&quot;&gt;SEE ALSO&lt;/a&gt;&lt;/li&gt;    &lt;ul&gt;    &lt;li&gt;&lt;a href=&quot;#books&quot;&gt;Books&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;#links&quot;&gt;Links&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;#modules&quot;&gt;Modules&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;#documentation&quot;&gt;Documentation&lt;/a&gt;&lt;/li&gt;    &lt;/ul&gt;&lt;li&gt;&lt;a href=&quot;#acknowledgements&quot;&gt;ACKNOWLEDGEMENTS&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#author&quot;&gt;AUTHOR&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#copyright&quot;&gt;COPYRIGHT&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr&gt;&lt;h3&gt;&lt;a name=&quot;name&quot;&gt;NAME&lt;/h3&gt;Jos&#39;s Guide for creating Perl modules&lt;h3&gt;&lt;a name=&quot;synopsis&quot;&gt;SYNOPSIS&lt;/h3&gt;Follow this guide to create good Perl distributions&lt;h3&gt;&lt;a name=&quot;description&quot;&gt;DESCRIPTION&lt;/h3&gt;From time to time, someone with little experience comes to me andasks: &quot;I&#39;d like to create a module. What do I do?&quot;&lt;p&gt;In order to answer that question to as many people as possible at thesame time, I decided to write this guide.&lt;h4&gt;&lt;a name=&quot;before_you_start&quot;&gt;Before you start&lt;/h4&gt;Before creating a module, use &lt;a href=&quot;http://search.cpan.org&quot;&gt;CPAN Search&lt;/a&gt; tosee if it already exists. If you don&#39;t find it at first, search for itunder different names; search for its functionality, rather than thename you&#39;d be giving it.&lt;p&gt;You should do this exhaustively so you don&#39;t waste your timeduplicating effort.&lt;p&gt;If your search on CPAN doesn&#39;t satisfy you, you can also searchGoogle. A lot of times, the right keywords are in the messages peoplepost about the module but not in the documentation.&lt;p&gt;Just because a namespace exists doesn&#39;t mean you should abandon yourmodule. See if it is any good, if it has everything you&#39;d like it tohave, and if it&#39;s being maintained. A good alternative is to contactthe author and ask him what he thinks about it. Maybe he&#39;ll give youthe namespace or you can also submit patches for the existing module.&lt;p&gt;If you need help with any of this, you can ask the PAUSE admins at&lt;a href=&quot;http://lists.perl.org/showlist.cgi?name=modules&quot;&gt;modules@perl.org&lt;/a&gt;.They will gladly help you with that, and sometimes they even havedifferent means to contact the person.&lt;h4&gt;&lt;a name=&quot;picking a good&quot;&gt;Picking a good name for your module&lt;/h4&gt;A module needs a good name that&#39;s intuitive, something that peoplesearch for, and describes the functionality it provides.&lt;p&gt;If you&#39;re having trouble deciding on a name for your module, send ane-mail to&lt;a href=&quot;http://lists.perl.org/showlist.cgi?name=module-authors&quot;&gt;module-authors@perl.org&lt;/a&gt;and&lt;a href=&quot;http://lists.perl.org/showlist.cgi?name=modules&quot;&gt;modules@perl.org&lt;/a&gt;.The readers can help you figure out a goodname.&lt;p&gt;If you have a name you&#39;re not sure about, keep that name in your mindfor a couple of days. If you don&#39;t think of anything better, it&#39;sprobably a good name. If the name is really bad, you&#39;ll probably thinkof another one during this time.&lt;h4&gt;&lt;a name=&quot;start_your_module&quot;&gt;Start your module&lt;/h4&gt;Sure, you can create your *.pm file, but don&#39;t forget the Makefile.PL,decent tests and the MANIFEST, along with META.yml and... wait aminute, you&#39;re not actually thinking of doing this all by yourself,are you?&lt;p&gt;As with several other tasks that people do on a daily basis, startinga module from scratch is a task that has been automated... severaltimes! This means you have a range of module creation tools to help you.&lt;h4&gt;&lt;a name=&quot;h2xs&quot;&gt;h2xs&lt;/h4&gt;A simple execution of h2xs is enough to create a module; here&#39;s anexample:&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;  h2xs -XAn My::New::Module&lt;/tt&gt;&lt;p&gt;The resulting structure is something like this (depending on yourversion of h2xs).&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;  .  `-- My-New-Module      |-- Changes      |-- MANIFEST      |-- Makefile.PL      |-- README      |-- lib      |   `-- My      |       `-- New      |           `-- Module.pm      `-- t          `-- My-New-Module.t&lt;/pre&gt;          &lt;p&gt;You&#39;re left with a directory with the name of your module, containinga Changes, MANIFEST, Makefile.PL, README, lib/ directory for yourmodules and a t/ directory for your tests. Not bad...&lt;p&gt;Without the -b switch, h2xs assumes your module requires your currentversion of Perl. If your module doesn&#39;t have any particular needs forthat version, change that! I have been a victim of this in the past,with people sending me e-mails saying &quot;Hey, your module requires Perl5.8.4, but it would run in 5.6.0. Could you please change that?&quot; Saveyourselves that trouble and check that.&lt;h4&gt;&lt;a name=&quot;module-starter&quot;&gt;module-starter&lt;/h4&gt;The module-starter script from [cpan://Module::Starter] asks for a few moreparameters to start with. Here&#39;s an example:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;  module-starter --module=My::New::Module --author=&quot;Me, Myself&quot; \    --email=myself@cpan.org&lt;/pre&gt;&lt;p&gt;Here&#39;s the resulting structure from this:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;  `-- My-New-Module      |-- Changes      |-- MANIFEST      |-- Makefile.PL      |-- README      |-- lib      |   `-- My      |       `-- New      |           `-- Module.pm      `-- t          |-- 00.load.t          |-- pod-coverage.t          `-- pod.t&lt;/pre&gt;&lt;p&gt;Looks pretty much the same as the result of h2xs, right? But don&#39;t letthat fool you! Apart from the new files that test your PODdocumentation, the contents of those files are different from the onesgenerated with h2xs. Give a try to both systems and check out thedifferences.&lt;p&gt;Currently, I use module-starter to start my own modules.&lt;h4&gt;&lt;a name=&quot;extutils&quot;&gt;ExtUtils::ModuleMaker&lt;/h4&gt;[cpan://ExtUtils::ModuleMaker] is another tool for creating modules. Using thecommand &lt;tt class=&quot;inline_code&quot;&gt;modulemaker&lt;/tt&gt; you are taken throught a menu. The resultingstructure would be something like this:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;  `-- My      `-- New          `-- Module              |-- Changes              |-- LICENSE              |-- MANIFEST              |-- Makefile.PL              |-- README              |-- Todo              |-- lib              |   `-- My              |       `-- New              |           `-- Module.pm              |-- scripts              `-- t                  `-- 001_load.t&lt;/pre&gt;&lt;p&gt;You can see some resemblances to the two other systems, right? Noticethe Todo and LICENSE files, as well as the scripts directory.&lt;h3&gt;&lt;a name=&quot;step_by_step&quot;&gt;Step by step: what to do&lt;/h3&gt;&lt;h4&gt;&lt;a name=&quot;document_first&quot;&gt;Document first&lt;/h4&gt;Now that you&#39;ve created the skeleton of your module, you shouldmove on to its guts, to its code, right?&lt;p&gt;&lt;b&gt;Wrong!&lt;/b&gt;&lt;p&gt;My personal opinion is that you should always start by thinking aboutwhat you&#39;re doing. This will save time in the long run.&lt;p&gt;Start with the documentation. My experience tells me that coding gets mucheasier after you&#39;ve documented every single one of your functions.&lt;p&gt;Before actually coding, write down the description of what everyfunction in the module should do. This gives you a chance to figureout what you are doing.&lt;p&gt;I usually keep a list of modules I&#39;d like to create. Rather thancreate them when I think about them, I take notes on themfrom time to time. When the right time comes, I use that list andpick one of the modules with the most notes. Then, I write thedocumentation.&lt;h4&gt;&lt;a name=&quot;create_tests&quot;&gt;Create tests&lt;/h4&gt;Make tests &lt;i&gt;before&lt;/i&gt; your code. I usually make mine at the same timeI&#39;m coding. I code a function, write its tests and test it.&lt;p&gt;Tests find things your eye wouldn&#39;t catch. As your module evolves,things you left behind can suddenly break. Tests will warn you aboutthem. You should test as much as you can. No test is a test too many.&lt;p&gt;Test for basic cases, but you should also test the extreme ones. Don&#39;tforget to test your functions with and without parameters, and evenwith parameters in excess, or wrong ones. You should know what thosefunctions return in each of those cases.&lt;p&gt;You should also test your documentation, but module-starter willautomatically create those tests for that, using [cpan://Test::Pod::Coverage]and [cpan://Test::Pod].&lt;h4&gt;&lt;a name=&quot;use_strict&quot;&gt;Use strict&lt;/h4&gt;Use strict! &quot;Strictures&quot; can warn you about things that otherwiseyou&#39;d be unaware of, like uninitialized variables and so on. Justput it at the top of all of your code files.&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;  use strict;&lt;/tt&gt;&lt;h4&gt;&lt;a name=&quot;use_warnings&quot;&gt;Use warnings&lt;/h4&gt;Warnings are good for your code and your sanity. &lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;  use warnings;&lt;/tt&gt;&lt;p&gt;Use &lt;tt class=&quot;inline_code&quot;&gt;warnings&lt;/tt&gt; and &lt;tt class=&quot;inline_code&quot;&gt;strict&lt;/tt&gt; at the very beginning ofscripts or modules.&lt;p&gt;But there is a downside to using warnings, though: they&#39;renot backwards compatible! If your code uses warnings, itwon&#39;t work with versions of Perl prior to 5.6. You can,however, use warnings while developing and remove them whenreleasing.&lt;p&gt;The latest version of [cpan://Test::Harness] turns on warnings whileyou test, so you might as well make your code warning free.&lt;h4&gt;&lt;a name=&quot;exports&quot;&gt;Exports&lt;/h4&gt;&lt;h5&gt;&lt;a name=&quot;how_it_works&quot;&gt;How it works&lt;/h5&gt;When you have a module, you probably have functions. When a user usesyour module, he has to import your functions into his program.&lt;p&gt;You&#39;re the one who chooses what he&#39;s able to import (that is, you canchoose not to let a particular function be imported) and how.&lt;p&gt;Here&#39;s an example, to make things easier:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;  require Exporter;  our @ISA = qw(Exporter);  our %EXPORT_TAGS = (          &#39;all&#39; =&gt; [ qw(                          function_make                          function_remove                          activate_all                          deactivate_all                  ) ],          &#39;action&#39; =&gt; [ qw(                          function_make                          function_remove                  ) ],          &#39;manipulation&#39; =&gt; [ qw(                          activate_all                          deactivate_all                  ) ],  );  our @EXPORT_OK = ( @{ $EXPORT_TAGS{&#39;all&#39;} } );  our @EXPORT = qw(                          function1  );&lt;/pre&gt;&lt;p&gt;Here&#39;s a brief explanation of what is going on in that code:&lt;p&gt;The last instruction (yes, we&#39;re starting by the end) states thatwhoever uses the module will always get &lt;tt class=&quot;inline_code&quot;&gt;function1&lt;/tt&gt;. The user getseverything in the @EXPORT array automatically.&lt;p&gt;The %EXPORT_TAGS hash is kind of an &#39;alias maker&#39;. In the example, thetag &lt;tt class=&quot;inline_code&quot;&gt;action&lt;/tt&gt; is mapped into &lt;tt class=&quot;inline_code&quot;&gt;function_make&lt;/tt&gt; and&lt;tt class=&quot;inline_code&quot;&gt;function_remove&lt;/tt&gt;,&lt;tt class=&quot;inline_code&quot;&gt;manipulation&lt;/tt&gt; is mapped into &lt;tt class=&quot;inline_code&quot;&gt;activate_all&lt;/tt&gt; and&lt;tt class=&quot;inline_code&quot;&gt;deactivate_all&lt;/tt&gt;,and &lt;tt class=&quot;inline_code&quot;&gt;all&lt;/tt&gt; is mapped in the four functions. When using a module likethis:&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;  use The::Module qw/:action/;&lt;/tt&gt;&lt;p&gt;The current package is importing &lt;tt class=&quot;inline_code&quot;&gt;function_make&lt;/tt&gt; and&lt;tt class=&quot;inline_code&quot;&gt;function_remove&lt;/tt&gt;.&lt;p&gt;The @EXPORT_OK is also very important. Things that are not in the@EXPORT variable can only be imported if they are included in@EXPORT_OK.&lt;p&gt;In this particular example, it&#39;s OK to import any of the fourfunctions comprised in the &lt;tt class=&quot;inline_code&quot;&gt;all&lt;/tt&gt; tag. This means one can do somethinglike this:&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;  use The::Module qw/:action activate_all/;&lt;/tt&gt;&lt;p&gt;He will get &lt;tt class=&quot;inline_code&quot;&gt;function_make&lt;/tt&gt;,&lt;tt class=&quot;inline_code&quot;&gt;function_remove&lt;/tt&gt;, &lt;tt class=&quot;inline_code&quot;&gt;activate_all&lt;/tt&gt; and&lt;tt class=&quot;inline_code&quot;&gt;function1&lt;/tt&gt; loaded in his package.&lt;h5&gt;&lt;a name=&quot;what_to_export&quot;&gt;What to export&lt;/h5&gt;So now that you have a couple of functions / methods implemented, youshould think on what to export...&lt;p&gt;If your module is purely object oriented, then you probably won&#39;texport anything.&lt;p&gt;However, if you have functions, you might feel a sudden urge to exportsome of them.&lt;p&gt;Don&#39;t!!!&lt;p&gt;Do not export functions just because. Instead, make them available tobe exported, but let the user select what he wants to use (but don&#39;tforget to document the possibilities, of course).&lt;p&gt;Plus, people HATE changes in the API, so think deeply about it. By notexporting anything, your API will remain the same when you add newfunctionalities to your module.&lt;p&gt;So, instead of adding those functions to @EXPORT, try adding them to@EXPORT_OK.&lt;h4&gt;&lt;a name=&quot;inside_your_distribution&quot;&gt;Inside your distribution&lt;/h4&gt;&lt;h5&gt;&lt;a name=&quot;keep_the_changes&quot;&gt;Keep the Changes up to date&lt;/h5&gt;The Changes file is there for a reason, right? Keep it up to date! Itwill help users know what you have changed (and therefore choosingwhether to download and install the new version or not); it will helpyou in case something gets broken from one version to the next one(because you&#39;ll know what you have changed); plus, you (and everybodyelse, for that matter) will be able to keep track of your work.&lt;h5&gt;&lt;a name=&quot;don_t_forget_the_readme&quot;&gt;Don&#39;t forget the README&lt;/h5&gt;The README file is really important. Not everybody reads it, but theyshould. That&#39;s why it is named README; because you&#39;re supposed to READIT!&lt;p&gt;Anyway, browsing a module on the CPAN, people will often look at theREADME, and if it isn&#39;t much, they will very likely take that as asign that your module isn&#39;t really finished.&lt;p&gt;Both h2xs and module-starter create a standard README file, which youshould change and add sections to as you feel the necessity for. Iusually copy the POD documentation of my main module to it.&lt;h5&gt;&lt;a name=&quot;the_manifest&quot;&gt;The MANIFEST&lt;/h5&gt;The MANIFEST file contains the list of all files to include in thedistribution (and only those get into it).&lt;p&gt;Whenever you add an extra file, don&#39;t forget to include it on theMANIFEST file, or your distribution will be incomplete (and,probably, broken).&lt;h5&gt;&lt;a name=&quot;makefile_pl&quot;&gt;Makefile.PL&lt;/h5&gt;There is a file called Makefile.PL. By looking at it, you might thinkthat you actually don&#39;t need to do anything to it; and that might betrue, most of the times.&lt;p&gt;If you used h2xs, you should check its parameters. Otherwise, youshould be fine.&lt;p&gt;However, there is one situation when you absolutely should updateMakefile.PL: when you use other modules. That is, when your module hasdependencies.&lt;p&gt;Just go there and add something like this:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;  PREREQ_PM =&gt; {      &#39;Another::Module&#39; =&gt; 0.01,  },&lt;/pre&gt;&lt;p&gt;That, for instance, states that your module depends on the existenceof at least version 0.01 of Another::Module.&lt;p&gt;This makes life easier for everybody. The user who&#39;s downloading andinstalling your module automatically doesn&#39;t have to spend timefiguring out the dependencies, for instance; and CPANPLUS will testyour module correctly (hopefully).&lt;p&gt;When testing, [cpan://Test::Prereq] might be a good option to check whetherthere are any modules you should add to PREREQ_PM (see section &quot;Maketests&quot;, down below).&lt;h5&gt;&lt;a name=&quot;version_numbers&quot;&gt;Version numbers&lt;/h5&gt;Whenever you release a new version, change the version number in yourmodule... and in the README... and be sure to include it in theChanges file too. It&#39;s really depressing when you upload a module andafterwards notice you got the version number wrong... (and it&#39;s evenmore depressing when you release the module again to get rid of thatannoyance and you do it again).&lt;p&gt;Do not go from version 0.01 to 1.00 and then to 2.00, because thatreally looks bad and you&#39;ll be in version 20.00 in no time. Instead,go from 0.01 to 0.02, and from there to 0.03, and so on.&lt;p&gt;Also, there isn&#39;t really the necessity of going to 1.00 just from0.99; people often change the integer part of the version (if one maycall it the integer part, given that it is usually a string) when theydo major changes in the design of the system, not when they run out ofnumbers.&lt;p&gt;Versions which are still being implemented usually have the currentversion number with an underscore and a number, like 0.04_01 and arecalled &quot;developer releases&quot;; the underscore makes it clear that thedistribution is not yet ready for the general public. You shouldfollow that practice. You can even upload a developer&#39;s release to theCPAN. When people look at your module they will see that version, witha red sign stating it&#39;s a developer&#39;s release and a link to the lastready-to-take version.&lt;h4&gt;&lt;a name=&quot;almost_done&quot;&gt;Almost done&lt;/h4&gt;&lt;h5&gt;&lt;a name=&quot;test_it_yourself&quot;&gt;Test it yourself&lt;/h5&gt;Before uploading your module, you should test it yourself. Use this tomake your distribution:&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;  make dist&lt;/tt&gt;&lt;p&gt;Suppose you had forgotten about including something in the MANIFEST,for instance. Just because your module passed all your tests in yourspecific directory doesn&#39;t mean it&#39;s working. &lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;  make disttest&lt;/tt&gt;&lt;p&gt;That should do it.&lt;h4&gt;&lt;a name=&quot;before_uploading&quot;&gt;Before uploading&lt;/h4&gt;Check your distribution before you upload it.&lt;ul&gt;&lt;li&gt;Are the tests OK? Are they enough? Do they cover everything? Did I test after I last changed something?&lt;/li&gt;&lt;li&gt;Did I get the version number right in three different places?&lt;/li&gt;&lt;li&gt;Did I change the default documentation both on the module and on the README?&lt;/li&gt;&lt;li&gt;Are all files in the MANIFEST?&lt;/li&gt;&lt;li&gt;Did I include all the dependencies in Makefile.PL?&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;&lt;a name=&quot;uploading&quot;&gt;Uploading&lt;/h4&gt;The &lt;a href=&quot;http://pause.perl.org&quot;&gt;PAUSE&lt;/a&gt; is the Perl&#39;s Authors Uploading Server. In orderto upload something to the CPAN, you need a PAUSE account.Get an account at &lt;a href=&quot;http://pause.perl.org&quot;&gt;PAUSE&lt;/a&gt;.&lt;p&gt;If you don&#39;t like the PAUSE web interface or you want toautomate it, or find it boring or whatever, you can take alook at &lt;tt class=&quot;inline_code&quot;&gt;release&lt;/tt&gt; and &lt;a href=&quot;/out/cpan/Module::Release&quot;&gt;Module::Release&lt;/a&gt;, which are toolsthat automatically upload files to the CPAN andSourceForge.net.&lt;h3&gt;&lt;a name=&quot;other_good_practices&quot;&gt;Other good practices&lt;/h3&gt;&lt;h4&gt;&lt;a name=&quot;release_early_release_often&quot;&gt;Release early, release often&lt;/h4&gt;You don&#39;t have to wait until your module is completed to release it.&quot;Release early, release often!&quot; You&#39;ll be moremotivated to do your work, people will be able to track yourprogress and might even give you some very important feedback on it.&lt;h4&gt;&lt;a name=&quot;good_style&quot;&gt;Good style&lt;/h4&gt;In the CPAN, good coding style might be the differencebetween you receiving patches or not, or even between peopleactually using your modules or not (because some programmersare too suspicious and feel the urge to understand everylittle piece of code they use).&lt;p&gt;Read &lt;tt class=&quot;inline_code&quot;&gt;perlstyle&lt;/tt&gt; and Perl::Tidy which show very goodways to tidy up your Perl code.&lt;h4&gt;&lt;a name=&quot;source_control&quot;&gt;Source control&lt;/h4&gt;Keep your code under a source control system, such as CVS,Subversion, or Perforce. You get backups, version controland lots of other advantages. Others who want to help can alsoaccess it if you make it public.&lt;h4&gt;&lt;a name=&quot;me_got_kwalitee&quot;&gt;Me got Kwalitee&lt;/h4&gt;The Kwalitee of your modules is not really Quality, but asclose as possible as an automatic Quality-measurer can be.&lt;p&gt;The Kwalitee project examines distributions on the CPAN forgood Perl coding practices, such as the use of strict,existence of tests, and so on. It assigns a score to eachdistribution, and therefore an average mean to the authors.&lt;p&gt;Strive for a high Kwalitee score is good for you, yourmodules, and its users. The higher Kwalitee you get, thebigger your ego becomes, and people consider your modules tobe higher quality.&lt;h4&gt;&lt;a name=&quot;other_things_you_should_know&quot;&gt;Other things you should know&lt;/h4&gt;&lt;h5&gt;&lt;a name=&quot;cpan_testers&quot;&gt;CPAN Testers&lt;/h5&gt;One of the best things about the CPAN is that your releases areactually tested by other people.&lt;p&gt;As a module author, you don&#39;t have to bother about it; you simplyupload your modules to the CPAN and wait to see if anything happens.&lt;p&gt;If your module&#39;s tests fail somewhere, you&#39;ll receive a report(actually, you&#39;re likely to receive quite a few, given that yourmodule will probably fail on other systems too).&lt;p&gt;Don&#39;t take it too hard if you receive an email with a subject startingwith &quot;FAIL Your::Module&quot;. It&#39;s nothing personal! You screwed up, butit&#39;s no big deal, because thanks to the CPAN Testers you are nowinformed of the problem and you can easily (hopefully) correct it andrelease a new version.&lt;p&gt;There, no harm done.&lt;h5&gt;&lt;a name=&quot;registering_modules&quot;&gt;Registering modules&lt;/h5&gt;Another thing you can do is to register the namespace ofyour module.&lt;p&gt;To do that, go to your PAUSE account and use the &quot;Registernamespace&quot; option, which is pretty simple to use. You&#39;llhave to elaborate on how and why is your moduleimportant, but it&#39;s not that difficult, really.&lt;p&gt;When people look at your home node on CPAN Search(http://search.cpan.org/~yourusername), they will see allyour modules and a list of the registered ones, along withsome information on those.&lt;p&gt;A registered module was approved by PAUSE admins.Therefore, it&#39;s not simply a product of some delusionalvisionist with headaches and is probably something good,unless, of course, some PAUSE admin that day was adelusional visionist and had an headache.&lt;h3&gt;&lt;a name=&quot;so_i_have_a_module&quot;&gt;So I have a module. Now what?&lt;/h3&gt;If you&#39;re thinking &quot;Time for another one&quot;, hold your horses there,pal! Creating module after module really isn&#39;t that hard; the hardthing is to maintain them all and keep them useful. Loads of moduleson their 0.01 versions that really don&#39;t do much and do have a list of&quot;promises&quot; don&#39;t do anyone much good, do they? Keepin mind that you should take all your modules to a stable version ofthem.&lt;p&gt;There&#39;s nothing wrong in having a bunch of modules you haven&#39;tcompleted yet, but there &lt;b&gt;is&lt;/b&gt; something wrong in having a bunch ofmodules you will &lt;b&gt;never&lt;/b&gt; complete.&lt;h3&gt;&lt;a name=&quot;final_words&quot;&gt;Final words&lt;/h3&gt;That said, I hope you now know a bit more than when you startedreading this document, and I hope it helps the Kwalitee... er...Quality of the CPAN modules around.&lt;p&gt;If you still have doubts (or maybe even more than when you started),there are lots of people willing to help (and of course I&#39;m one ofthem).&lt;p&gt;Check out the&lt;a href=&quot;http://lists.perl.org/showlist.cgi?name=modules&quot;&gt;modules@perl.org&lt;/a&gt; mailing list.&lt;p&gt;For anything else, I&#39;m cog at cpan dot org.&lt;h3&gt;&lt;a name=&quot;see_also&quot;&gt;SEE ALSO&lt;/h3&gt;&lt;h4&gt;&lt;a name=&quot;books&quot;&gt;Books&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://apress.com/book/bookDisplay.html?bID=14&quot;&gt;Writing Perl Modules for CPAN, by Sam Tregar&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;&lt;a name=&quot;links&quot;&gt;Links&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://langworth.com/PerlTestCard&quot;&gt;Perl Testing Reference Card&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.steve.gb.com/perl/lesson08.html&quot;&gt;Perl tutorial Lesson 8&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://cpants.dev.zsi.at/&quot;&gt;Kwalitee&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://domm.zsi.at/talks/cpants/&quot;&gt;CPAN Testing Service (CPANTS)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://magnonel.guild.net/~schwern/talks/CPANTS/full_slides/&quot;&gt;http://magnonel.guild.net/~schwern/talks/CPANTS/full_slides/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://lists.perl.org/showlist.cgi?name=module-authors&quot;&gt;Perl module author&#39;s mailing list, module-authors@perl.org&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://lists.perl.org/showlist.cgi?name=modules&quot;&gt;Perl authors upload server (PAUSE) mailing list, modules@perl.org&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;&lt;a name=&quot;modules&quot;&gt;Modules&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;/out/cpan/Exporter&quot;&gt;Exporter&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/out/cpan/ExtUtils::ModuleMaker&quot;&gt;ExtUtils::ModuleMaker&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/out/cpan/Module::Release&quot;&gt;Module::Release&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/out/cpan/Module::Starter&quot;&gt;Module::Starter&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/out/cpan/Perl::Tidy&quot;&gt;Perl::Tidy&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/out/cpan/Test::More&quot;&gt;Test::More&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/out/cpan/Test::Prereq&quot;&gt;Test::Prereq&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;&lt;a name=&quot;documentation&quot;&gt;Documentation&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;/out/doc/perlmodlib&quot;&gt;perlmodlib&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/out/doc/perlmodstyle&quot;&gt;perlmodstyle&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/out/doc/perlnewmod&quot;&gt;perlnewmod&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/out/doc/perlstyle&quot;&gt;perlstyle&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;&lt;a name=&quot;acknowledgements&quot;&gt;ACKNOWLEDGEMENTS&lt;/h3&gt;This guide was loosely based on &lt;a href=&quot;/html/376075.html&quot;&gt;brian&#39;s Guide to Solving Any Perl Problem&lt;/a&gt; (which you should read, too).&lt;p&gt;&lt;a href=&quot;http://alfarrabio.di.uminho.pt/~albie/&quot;&gt;Alberto Simes&lt;/a&gt; and &lt;a href=&quot;http://www.panix.com/~comdog/&quot;&gt;brian d foy&lt;/a&gt; made really good suggestions for sections to add to this document, as well as some changes to the existing ones.&lt;h3&gt;&lt;a name=&quot;author&quot;&gt;AUTHOR&lt;/h3&gt;Jos Castro, cog at cpan dot org&lt;h3&gt;&lt;a name=&quot;copyright&quot;&gt;COPYRIGHT&lt;/h3&gt;Copyright 2004, Jos Castro, Creative Commons license.
    </description>
</item>

        

<item>
    <title>Perl White Magic - Special Variables and Command Line Switches (cog)</title>
    <link>http://prlmnks.org/html/431511.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/431511.html</guid>

    <description>
        &lt;h3&gt;Context&lt;/h3&gt;This tutorial on Special Variables and Command Line Switches was originally published in the YAPC::EU::2004 proceedings (where it was awarded the prize for best paper).&lt;p&gt;&lt;small&gt;(hopefully, when translating the tex to html, I haven&#39;t screwed up anything O:-) )&lt;/small&gt;&lt;h2&gt;Prologue&lt;/h2&gt;Everything was silent, but for the two of them breathing.&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;All my life I&#39;ve felt there was more to system administration thanthis... And now... now that you&#39;ve arrived... now I know I wasright!&#39;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;You really think I&#39;ll be up to the job, &lt;b&gt;Command Line&lt;/b&gt;?&#39;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Yes, you will. You will, &lt;b&gt;$_&lt;/b&gt;.&#39;&lt;h2&gt;Super-powers come to those who wait&lt;/h2&gt;&lt;b&gt;$_&lt;/b&gt; woke up with a sudden and loud noise. It would have sounded like a fan,should he know what a fan was.&lt;br&gt;He knew there were things to be done, and that sooner or later he would becalled into aid. He did not know, however, what those particular thingswere and who would be in charge of choosing how and what to do exactly.&lt;br&gt;As soon as these thoughts crossed his mind, gravity suddenly disappeared. Somekind of magnet picked him up and promptly took him to the top of a script,right after a &lt;b&gt;shebang&lt;/b&gt;.&lt;br&gt;Beneath him, comments could be seen.&lt;p&gt;Commented code can mean an awfull lot of different things, and &lt;b&gt;$_&lt;/b&gt; knew thisbetter than any other variable. It can be meant to identify the Creator or thepurpose of life, but can also exist just to state that something is yetunfinished. One would hope it was not the case...&lt;p&gt;Slowly at first, he started going down the script. Slowly enough to read thecomments:&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;        # counts words and lines in a file&lt;/tt&gt;&lt;p&gt;He passed that line and saw the next following ones:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        while (&lt;&gt;) {                @words = split /\W+/;                $words += @words;        }        print &quot;lines -&gt; $.\nwords -&gt; $words\n&quot;;&lt;/pre&gt;&lt;p&gt;Not knowing what to do, he started feeling anxious as gravity pulled him nearerto his destiny. At this point, &lt;b&gt;Command Line&lt;/b&gt; shouted at him:&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Use the monitor on your wrist!!&#39;&lt;p&gt;He looked at his wrist and saw something that resembled a smaller version ofsomething someone wanting to hitchhike through the galaxy would take as a guide,but it was actually something someone wanting to hitchhiking through a &lt;b&gt;Perl&lt;/b&gt;script would take as a guide. Plus, it had no &quot;Don&#39;t Panic&quot; stuff; instead, ithad &lt;b&gt;Perldoc&lt;/b&gt; written on it.&lt;br&gt;He quickly turned it on and searched for &lt;b&gt;split&lt;/b&gt; (he already knew what a&lt;b&gt;while&lt;/b&gt; was). He realized that being called with a single argument,&lt;b&gt;split&lt;/b&gt; would need him to complete his task.&lt;br&gt;Knowing this, and reaching that line (several times in a row), &lt;b&gt;$_&lt;/b&gt; took hisplace in front of the split.&lt;br&gt;&lt;b&gt;ZAP&lt;/b&gt;!!! &lt;b&gt;ZAP&lt;/b&gt;!!!&lt;br&gt;His contents were instantely splited up and the resulting array was counted,having that result summed up to &lt;b&gt;$words&lt;/b&gt;.&lt;br&gt;After exiting the &lt;b&gt;while&lt;/b&gt;, &lt;b&gt;$_&lt;/b&gt; met &lt;b&gt;$.&lt;/b&gt;:&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Hi&#39;, said &lt;b&gt;$_&lt;/b&gt;.&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Hi.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Who are you?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;I&#39;m &lt;b&gt;$.&lt;/b&gt;.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;That I can see, but... exactly what are you doing here?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;I am counting lines.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;What lines have you been counting if I&#39;ve been through all of them and neversaw you?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;I see you&#39;re not familiar with special variables... I would advise you tomake use of that little device on your wrist and search for &lt;b&gt;perlvar&lt;/b&gt;.&#39;&lt;p&gt;So he did, and promptly understood what a special variable was: they werethere, they just couldn&#39;t be seen... &lt;b&gt;$.&lt;/b&gt;, in particular, had beencounting the input lines right from the beginning of the script, and was readyto pop into action when called... and so it did.&lt;br&gt;Not a second after realizing all this, &lt;b&gt;$_&lt;/b&gt; was pulled back to where he wasbefore. &lt;b&gt;Command Line&lt;/b&gt; walked near him for a while:&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;How do you feel?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;... Strange...&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Don&#39;t worry, you&#39;ll get over it. Happens to all of us. Soon you&#39;ll be readyfor more.&#39;&lt;h2&gt;Different perspectives&lt;/h2&gt;As before, &lt;b&gt;$_&lt;/b&gt; was taken again by the strange force. He was ready for it beforeit started, but then came the surprise...&lt;br&gt;Strangely enough, this time he wasn&#39;t moving vertically, but ratherhorizontally... Everything resembled an assembly line.&lt;br&gt;The first thing he noticed was a command line switch, but he did not know whatone was yet. He reached the monitor on his wrist and started hitting itdesperately. He eventually strolled across &lt;b&gt;perlrun&lt;/b&gt; and searched for it.He found it:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        -e commandline            may be used to enter one line of program.&lt;/pre&gt;&lt;p&gt;That explained the horizontal movement.&lt;br&gt;Looking back and forward, he saw the complete line of code:&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;        perl -e &#39;while (&lt;&gt;) {$w += split /\W+/} print &quot;$. $w\n&quot;&#39;&lt;/tt&gt;&lt;p&gt;He could now understand what was going on. This was practically the same scriptas before, except now it wasn&#39;t a script anymore, it was an &quot;One-Liner&quot;, one ofthe most beautiful creations by the hand and mind of the OriginalCreator &lt;small&gt;(The one and only: Larry Wall)&lt;/small&gt;.&lt;br&gt;The whole line resumed as expected, and he was on his way back home when he wassuddenly pulled back again into action.&lt;br&gt;He saw a weird switch, this time. It was &lt;b&gt;-ne&lt;/b&gt;. He looked it up butcouldn&#39;t find it. He was staring at the beginning of chapter &quot;CommandSwitches&quot;, wondering, when he read something that washed away any doubt:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        As with all standard commands, a single-character switch       may be clustered with the following switch, if any.           #!/usr/bin/perl -spi.orig   # same as -s -p -i.orig&lt;/pre&gt;&lt;p&gt;&lt;b&gt;-ne&lt;/b&gt; was surely the same as &lt;b&gt;-n -e&lt;/b&gt;, and he already knew one ofthem. He looked for the other and promptly found it:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        -n   causes Perl to assume the following loop around            your program [...]              LINE:                while (&lt;&gt;) {                    ...             # your program goes here                }&lt;/pre&gt;&lt;p&gt;He looked at the rest of the line to get a better feel of what was going on:&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;        perl -ne &#39;$w+=split /\W+/; END{print&quot;$w $.\n&quot;}&#39;&lt;/tt&gt;&lt;p&gt;Everything seemed OK now. He already knew that any &lt;b&gt;END&lt;/b&gt; block was to beexecuted only at the end of the script, after everything else. The programwould go like this:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        LINE:          while (&lt;&gt;) {                  $w += split /\W+/;                  END { print&quot;$w $.\n&quot; }          }&lt;/pre&gt;&lt;p&gt;That was rather close to his first task, but with less coding going around.&lt;br&gt;He finished his task and rushed for another one; this time it was a scriptinside a file again:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        #!/usr/bin/perl -n        # counts words and lines in a file        @words = split /\W+/;        $words = @words;        END { print &quot;lines -&gt; $.\nwords -&gt; $words\n&quot;; }&lt;/pre&gt;&lt;p&gt;Someone was obviously doing experiments, but that was good for him, as he wassurely learning from it.&lt;br&gt;By knowing the &lt;b&gt;-n&lt;/b&gt; switch, someone had actually shrinked the code.&lt;br&gt;He would have asked &lt;b&gt;-n&lt;/b&gt; what he though about it, but everyone knowscommand line switches don&#39;t speak. That would be just stupid.&lt;br&gt;&lt;b&gt;$_&lt;/b&gt; went home and rested for a while.&lt;h2&gt;A whole bag of switches&lt;/h2&gt;Again, the same startup routine. This time, the user was noticeably moreexperienced:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        #!/usr/bin/perl -w        use strict;&lt;/pre&gt;&lt;p&gt;At least he seemed to know what he was doing. Every good script should startwith something like that. The &lt;b&gt;Perldoc&lt;/b&gt; screen told him:&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;        -w   prints warnings about dubious constructs&lt;/tt&gt;&lt;p&gt;One should always use it.&lt;br&gt;Below, another comment:&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;        #Adding a commit each 100 lines&lt;/tt&gt;&lt;p&gt;He had heard something about this... DBA&#39;s sometimes have troubleinserting too many rows in a table, as that very same information is kept asroolback data between &lt;b&gt;commit&lt;/b&gt; instructions(so everything can be undone, if needed).&lt;br&gt;Adding a &lt;b&gt;commit&lt;/b&gt; each 100 lines would solve this problem, as the maximumof information kept at a time would consist of 100 records.&lt;br&gt;Following, the code:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        my $line;        while (&lt;&gt;) {          $line++;          unless ( $line % 100 ) {            print &quot;commit;\n&quot;;          }          print;        }&lt;/pre&gt;&lt;p&gt;It wasn&#39;t as complicated as it would seem at first. He noticed the &lt;b&gt;$line&lt;/b&gt;part could be replaced with &lt;b&gt;$.&lt;/b&gt;, and the rest of the code could beshortened with the &lt;b&gt;-n&lt;/b&gt;, but he really wasn&#39;t expecting what happened inhis next task.&lt;br&gt;Just after finishing this, he was called again into action. He was getting usedto this and wouldn&#39;t get dizzy anymore.&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        #!/usr/bin/perl -wp        use strict;        #Adding a commit each 100 lines        unless ( $. % 100 ) { print &quot;commit;\n&quot;; }&lt;/pre&gt;&lt;p&gt;He looked up for &lt;b&gt;-p&lt;/b&gt;:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        -p   causes Perl to assume the following loop around            your program [...]              LINE:                while (&lt;&gt;) {                    ...             # your program goes here                } continue {                    print or die &quot;-p destination: $!\n&quot;;                }&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;So that&#39;s why the print statement has been removed.&#39;&lt;p&gt;It simply wasn&#39;t needed anymore, as the &lt;b&gt;-p&lt;/b&gt; switch would do the same as&lt;b&gt;-n&lt;/b&gt; and also print each line.&lt;br&gt;He was pondering about this, when yet another surprise called for hisattention. He was, once again, in the &lt;b&gt;Command Line&lt;/b&gt;; the user was making use ofthe &lt;b&gt;-e&lt;/b&gt; switch once again:&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;        perl -i -pe &#39;print &quot;commit;\n&quot; unless ($.%100)&#39;&lt;/tt&gt;&lt;p&gt;He knew what to do:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        -i[extension]            specifies that files processed by the &quot;&lt;&gt;&quot;            construct are to be edited in-place.  It does            this by renaming the input file, opening [...]&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Wow.&#39; He couldn&#39;t help the remark.&lt;p&gt;That meant the input was to be read, processed, and then rewritten over theoriginal file. This would probably save the user the trouble of copying a newfile over an older one.&lt;br&gt;He was taken back to his home.&lt;br&gt;How many more switches would he meet?&lt;h2&gt;They come in pairs&lt;/h2&gt;The same routine. Once again, &lt;b&gt;$_&lt;/b&gt; was ready for surprises and had his &lt;b&gt;Perldoc&lt;/b&gt;prepared.&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        #!/usr/bin/perl -wlp        use strict;        # trims lines to 80 columns        substr($_, 80) = &quot;&quot;;&lt;/pre&gt;&lt;p&gt;He looked up &lt;b&gt;-l&lt;/b&gt; and, to his surprise, he found the exact code he wasrunning on. Hum... the user probably had a &lt;b&gt;Perldoc&lt;/b&gt; of his own... (Perhaps hewas a special variable too?) The text on &lt;b&gt;-l&lt;/b&gt; would go:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        -l[octnum]            enables automatic line-ending processing.&lt;/pre&gt;&lt;p&gt;After reading a little bit more, he understood what was going on: the trailing&quot;&lt;b&gt;\n&lt;/b&gt;&quot; on each line would be discarded, each line would be trimmed up to80 chars and printed with the &quot;&lt;b&gt;\n&lt;/b&gt;&quot; back on. He noticed the textmentioned two other variables: &lt;b&gt;$/&lt;/b&gt; and &lt;b&gt;$\&lt;/b&gt;... and their namessounded fierce.&lt;p&gt;Usually, one goes from more code to less code, and not the other way around,but this was exactly what happened next. His next script, instead of using the&lt;b&gt;-l&lt;/b&gt; switch, seemed to do the same by using those very same two variables.The user was obviously up to something (probably just testing and learning newfeatures).&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        #!/usr/bin/perl -wp        use strict;        # trims lines to 80 columns        chomp;        $\ = $/;        substr($_, 80) = &quot;&quot;&lt;/pre&gt;&lt;p&gt;Dazzled in astonishment, he didn&#39;t even think about reaching for his &lt;b&gt;Perldoc&lt;/b&gt;. Heinstead asked the variables directly what they were up to.&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Hi.&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Can&#39;t you see we&#39;re busy?&#39; said &lt;b&gt;$/&lt;/b&gt;.&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;I&#39;m sorry, but I&#39;m new at this, and so many special variables and commandswitches are starting to mess with my mind...&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Oh, a beginner...&#39; said &lt;b&gt;$\&lt;/b&gt;.&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Indeed, a beginner.&#39; &lt;b&gt;$/&lt;/b&gt; agreed.&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Yes. I was wondering who you guys are, and what you are doing.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;I am the input record separator. Usually, I contain a &quot;&lt;b&gt;\n&lt;/b&gt;&quot;&#39;, explained&lt;b&gt;$/&lt;/b&gt;.&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;And I am the output record separator... usually containing nothing...&#39;sighed &lt;b&gt;$\&lt;/b&gt;, with a slight note of disappointment.&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;And what are you doing?&#39; asked &lt;b&gt;$_&lt;/b&gt;.&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;We&#39;re swapping contents.&#39; said &lt;b&gt;$\&lt;/b&gt;.&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Yes, it&#39;s a rather common practice.&#39; Continued &lt;b&gt;$/&lt;/b&gt;.&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Actually, it&#39;s so common that someone actually invented a switch for this.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;So I noticed. &lt;b&gt;-l&lt;/b&gt;, isn&#39;t it?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;So you&#39;ve seen it too, uh?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Yes.&#39;&lt;p&gt;As good as the conversation was getting, &lt;b&gt;$_&lt;/b&gt; noticed the end of the scriptarriving.&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;What&#39;s the purpose of what you&#39;re doing?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Well, you see, most of the times you print something, you&#39;re actually printinga line, but that means you have to print the &quot;&lt;b&gt;\n&lt;/b&gt;&quot; too, as the commonprint statement does not assume that. However, by making use of &lt;b&gt;$\&lt;/b&gt; here,you have no need of doing that...&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Yes, I&#39;ll do it for you!&#39; interrupted &lt;b&gt;$\&lt;/b&gt; &#39;Just give me whateveryou want printed on every line, and I&#39;ll take care of it for you! We&#39;re closefriends, &lt;b&gt;print&lt;/b&gt; and I.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Wow... that&#39;s nice...&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Yes, and that&#39;s not all. You should see what *I* can do!&#39; said &lt;b&gt;$/&lt;/b&gt;.&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Really, what can you do?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Later, my friend, here comes &lt;b&gt;EOF&lt;/b&gt; to take us home.&#39;&lt;p&gt;So that was the name of this magnet: &lt;b&gt;EOF&lt;/b&gt;.&lt;h2&gt;The mighty variable&lt;/h2&gt;&lt;b&gt;$_&lt;/b&gt; fell asleep with &lt;b&gt;$/&lt;/b&gt; on his head, and woke up still thinking aboutit.&lt;br&gt;He was called into action and, to his contentment, there was &lt;b&gt;$/&lt;/b&gt;:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        #!/usr/bin/perl -wpi        use strict;        $/ = &quot;&quot;;        while(&lt;&gt;) {                chomp;                print &quot;$_\n&quot;;        }&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Hi.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Hi.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;I can&#39;t see any comments on this script. What&#39;s going on?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;We&#39;re joining paragraphs.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;What do you mean?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;I mean we&#39;re joining paragraphs. Those having more than two blank linesbetween them are being pushed closer to each other. Basically, we&#39;renormalizing text.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;I see... And how exactly are we doing that? And what&#39;s your part in allthis?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Well, as I told you before, I am the input record separator, which means I&#39;mthe one who decides the input that gets in at a time. Regularly, I have astring (usually &quot;&lt;b&gt;\n&lt;/b&gt;&quot;), which is what I use to make that decision,spliting the input on that string, but I do have a couple of more tricks up mysleeve...&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;I can imagine that. Are you using one of those right now?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Yes. I am using the paragraph mode. By assigning me to an empty string, theuser gets me to separate input at blank lines. Basically, at &quot;&lt;b&gt;\n\n+&lt;/b&gt;&quot;.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;I see. But why not assigning you to &quot;&lt;b&gt;\n\n+&lt;/b&gt;&quot; directly?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Hey, kiddo! See me flying?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;No...&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Know why?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Why?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;That&#39;s because I&#39;m a special variable, not a super variable. I can&#39;t dealwith regular expressions.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Hum... And I assume a simple &quot;&lt;b&gt;\n\n&lt;/b&gt;&quot; wouldn&#39;t suffice, as thatwouldn&#39;t get all the cases...&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;You assume correctly. I would take &quot;&lt;b&gt;\n\n\n\n&lt;/b&gt;&quot;, for instance, and findanother record in the middle of it. Hence, paragraph mode.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Wow... Nice trick!&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Thanks.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Too bad you don&#39;t do regular expressions, though...&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;It&#39;s not that bad, really. Anyway, &lt;b&gt;awk&lt;/b&gt; has to be better for something.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;I suppose you&#39;re right. What about your other tricks?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Well, I can be assigned to a reference to an integer, a scalar containing aninteger or a scalar that&#39;s convertible to an integer...&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;And what will that do?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Given that integer, I will read that many bytes at a time.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Wow.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Gotta go. Bye.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;See you around.&#39;&lt;p&gt;That night, &lt;b&gt;$_&lt;/b&gt; had trouble falling asleep, dreaming of the possibilities those&lt;b&gt;$/&lt;/b&gt;&#39;s tricks could mean.&lt;h2&gt;Separations&lt;/h2&gt;Yet another day.&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;        perl -ane &#39;print shift(@F), &quot;\n&quot;&#39;&lt;/tt&gt;&lt;p&gt;Everything was so easy now that he was used to &lt;b&gt;Perldoc&lt;/b&gt;. He was even able to opentwo windows at a time, one with &lt;b&gt;perlrun&lt;/b&gt; and another with &lt;b&gt;perlvar&lt;/b&gt;.He used the first one to search for &lt;b&gt;-a&lt;/b&gt;:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        -a   turns on autosplit mode when used with a -n or            -p.  An implicit split command to the @F array            is done as the first thing inside the implicit            while loop produced by the -n or -p.                perl -ane &#39;print pop(@F), &quot;\n&quot;;&#39;            is equivalent to                while (&lt;&gt;) {                    @F = split(&#39; &#39;);                    print pop(@F), &quot;\n&quot;;                }&lt;/pre&gt;&lt;p&gt;and the second for &lt;b&gt;@F&lt;/b&gt;:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        @F      The array @F contains the fields of each               line read in when autosplit mode is turned               on. [...]&lt;/pre&gt;&lt;p&gt;To tell the truth, the entry for &lt;b&gt;-a&lt;/b&gt; already explained what &lt;b&gt;@F&lt;/b&gt; wasdoing there. Anyway, the code in the documentation was very similar to the onehe was running on. He was clearly on a script for printing the first word ofevery input line. What for? He would soon find out.&lt;br&gt;Next, he passed the following code:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        #!/usr/bin/perl -wane        use strict        # study commands (input is .bash_history)        $commands{shift(@F)}++;        END {                for (keys %commands) {                        print &quot;$_ -&gt; $commands{$_}\n&quot;                }        }&lt;/pre&gt;&lt;p&gt;This was a very simple way of studying how often commands are ran on thesystem.&lt;br&gt;There was still another line of documentation, regarding &lt;b&gt;-a&lt;/b&gt;:&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;        An alternate delimiter may be specified using -F.&lt;/tt&gt;&lt;p&gt;Another switch. And soon he would see and example of its usage:&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;        perl -F: -ane &#39;print shift(@F),&quot;\n&quot;&#39;&lt;/tt&gt;&lt;p&gt;Hum... this would split the input lines on &#39;&lt;b&gt;:&lt;/b&gt;&#39; and print every firstelement of those lines. (Maybe it would run on &lt;b&gt;/etc/passwd&lt;/b&gt;, for alist of users)&lt;h2&gt;TIMTOWTDI&lt;/h2&gt;&lt;b&gt;Command Line&lt;/b&gt; approached &lt;b&gt;$_&lt;/b&gt; softly and woke him gently:&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Wake up, &lt;b&gt;$_&lt;/b&gt;!&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;What is it?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Come, you&#39;re going to learn an important lesson today.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;OK.&#39;&lt;p&gt;They walked along for a while.&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;So what&#39;s this lesson I&#39;m going to learn?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Be patient, my friend. Look, here&#39;s your first script for today!&#39;&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        #!/usr/bin/perl -w        use strict;        my @a = (1, 2, 3, 4, 5);        print &quot;@a&quot;;&lt;/pre&gt;&lt;p&gt;&lt;b&gt;$_&lt;/b&gt; went through it as if he hadn&#39;t been doing anything else all his life.&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;There.&#39;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Very good. Did you notice the output?&#39;&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;        1 2 3 4 5&lt;/tt&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Cool...&#39;, said &lt;b&gt;$_&lt;/b&gt;, &#39;&lt;b&gt;Perl&lt;/b&gt; already knows he has to put a space betweenthose elements, right?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Wrong. The truth is &lt;b&gt;Perl&lt;/b&gt; knows he has to put something between thoseelements, allright. You&#39;re about to meet that something.&#39;&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        #!/usr/bin/perl -w        use strict;        my @a = (1, 2, 3, 4, 5);        $&quot; = &quot;|&quot;;        print &quot;@a&quot;;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Done!&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Well done. Now, did you notice the difference?&#39;&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;        1|2|3|4|5&lt;/tt&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Yes. I assume &lt;b&gt;Perl&lt;/b&gt; takes the contents of &lt;b&gt;$&quot;&lt;/b&gt; and prints that everytimean array is printed. Right?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Wrong again... &lt;b&gt;Perl&lt;/b&gt; only uses &lt;b&gt;$&quot;&lt;/b&gt; if the array is inside quotes.Take a look at our next example!&#39;&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        #!/usr/bin/perl -w        use strict;        my @a = (1, 2, 3, 4, 5);        print @a;&lt;/pre&gt;&lt;p&gt;&lt;b&gt;$_&lt;/b&gt; went through it.&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Now look at the output produced.&#39;&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;        12345&lt;/tt&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Odd... shouldn&#39;t a space be there too, separating elements?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;No. When not quoted, an array to be printed is joined with the contents of&lt;b&gt;$,&lt;/b&gt;, and that variable is empty by default. Next example!&#39;&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        #!/usr/bin/perl -w        use strict;        my @a = (1, 2, 3, 4, 5);        $, = &quot;-&quot;;        print @a;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;And now the output!&#39;&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;        1-2-3-4-5&lt;/tt&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;See?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Yes... Interesting...&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Indeed. Let&#39;s go.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;OK...&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;See how you can do the same with two different variables?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Yes.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;That&#39;s your lesson for today. There&#39;s more than one way to do it!&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;I see...&#39;&lt;p&gt;&lt;b&gt;$_&lt;/b&gt; was clever enough to remain silent for a while and think about what &lt;b&gt;Command Line&lt;/b&gt; hadjust said... &quot;There&#39;s more than one way to do it!&quot;&lt;h2&gt;Thoughts&lt;/h2&gt;&#39;I like it here.&#39; exclaimed &lt;b&gt;$_&lt;/b&gt;. &#39;All these switches and specialvariables, being famous and loved by all.&#39;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;That&#39;s not entirely true... Some variables are not very well known, andothers are not very appreciated.&#39; replied &lt;b&gt;Command Line&lt;/b&gt;.&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;For instance...?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;&lt;b&gt;$.&lt;/b&gt;.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Really? Is that true?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Yes, it is.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Who doesn&#39;t appreciate it?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;YAPC speakers who have to write articles with sentences ending in &lt;b&gt;$.&lt;/b&gt;.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Why? I don&#39;t see any problem with a sentence ending in &lt;b&gt;$.&lt;/b&gt;.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Oh, but there are problems with sentences ending in &lt;b&gt;$.&lt;/b&gt;.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;I really can&#39;t see what&#39;s wrong with &lt;b&gt;$.&lt;/b&gt;...&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Then you probably didn&#39;t pay attention to the four previous lines.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Oh! That! I didn&#39;t realize that... Boy, it must really suck, being theonly variable some people don&#39;t like.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Oh, not the only one...&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Who else, then?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Guess.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;&lt;b&gt;$,&lt;/b&gt;, &lt;b&gt;$?&lt;/b&gt;?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Those and &lt;b&gt;$!&lt;/b&gt;!&#39;&lt;h2&gt;Modules and one-liners&lt;/h2&gt;&lt;b&gt;$_&lt;/b&gt; was on the move again.&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;        perl -MExtUtils::Installed -le &#39;                print for ExtUtils::Installed-&gt;new()-&gt;modules&#39;&lt;/pre&gt;&lt;p&gt;He looked &lt;b&gt;-M&lt;/b&gt; on &lt;b&gt;Perldoc&lt;/b&gt; and was preparing to look for &lt;b&gt;-E&lt;/b&gt; too when henoticed there was no need for that...&lt;br&gt;&lt;b&gt;-M&lt;/b&gt;, according to &lt;b&gt;Perldoc&lt;/b&gt;, would do the same as a &lt;b&gt;use&lt;/b&gt; clauseinside the script. Basically, that line was the same thing as&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;perl -        le &#39;use ExtUtils::Installed;                print for ExtUtils::Installed-&gt;new()-&gt;modules&#39;&lt;/pre&gt;&lt;p&gt;The &lt;b&gt;E&lt;/b&gt; was actually the beginning of a parameter for the &lt;b&gt;-M&lt;/b&gt;switch.&lt;br&gt;He also looked for documentation on that module (with &lt;b&gt;Perldoc&lt;/b&gt;, too). He foundit and came to the conclusion that that line of code would print the name ofevery &lt;b&gt;Perl&lt;/b&gt; module installed. That was a nice way to know what was on thesystem.&lt;h2&gt;The sky is the limit&lt;/h2&gt;&#39;I think I&#39;m getting the hang of this.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;There is still much to learn, &lt;b&gt;$_&lt;/b&gt;.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Are there more special variables?&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Quite a few. And some more command line switches, too.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Wow... This is just amazing...&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;I&#39;m glad you like it. However, we won&#39;t have the time to go through all ofthem now.&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Oh... That&#39;s too bad...&#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;- &#39;Don&#39;t worry. There are lots of places where you can learn more, and &lt;b&gt;Perldoc&lt;/b&gt; is oneof them.&#39;&lt;p&gt;&lt;b&gt;$_&lt;/b&gt; stared at his &lt;b&gt;Perldoc&lt;/b&gt;.&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;And besides that, you have lots of mailing lists, perlmonks, etc. You&#39;ll neverrun out of information. The trick is to keep practising.&#39;&lt;p&gt;&lt;b&gt;$_&lt;/b&gt; smiled.&lt;h2&gt;Revelations&lt;/h2&gt;&lt;b&gt;$_&lt;/b&gt; was browsing his &lt;b&gt;Perldoc&lt;/b&gt; and talking to &lt;b&gt;Command Line&lt;/b&gt;:&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;&lt;b&gt;Perl&lt;/b&gt; really seems to be a wonderful language, and all the special variablesand command line switches take an important part in it.&#39;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Yes, but there is much more than that to &lt;b&gt;Perl&lt;/b&gt;.&#39;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Really?&#39;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Yep. You should wait to read some of the other articles the author of thisone is thinking of writing.&#39;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Wow... I can see why the user chose &lt;b&gt;Perl&lt;/b&gt;.&#39;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Yes, but it wasn&#39;t like that in the beginning.&#39;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Really?&#39;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;Really. Things were a lot different, until the moment he had an epiphany,and heard a voice saying: &quot;Don&#39;t try to do everything with the &lt;b&gt;Bash&lt;/b&gt;. Instead,only try to realize the truth.&quot;&#39;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;What truth?&#39;&lt;p&gt;&amp;nbsp;&amp;nbsp;- &#39;There is no &lt;b&gt;Bash&lt;/b&gt;.&#39;
    </description>
</item>

        

<item>
    <title>How to install Win32::OLE under Linux? (dpavlin)</title>
    <link>http://prlmnks.org/html/430194.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/430194.html</guid>

    <description>
        &lt;p&gt;I wanted to run [cpan://Win32::OLE]on my development machine which is Debian Linux. This tutorial is based on&lt;a href=&quot;http://www.codeweavers.com/&quot;&gt;CrossOver Office Standard&lt;/a&gt; 4.1,but it should also work with &lt;a href=&quot;http://www.winehq.com/&quot;&gt;Wine&lt;/a&gt; (not tested).&lt;/p&gt;&lt;ul&gt;&lt;li&gt; Download and install &lt;a href=&quot;http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;FamilyID=CEBBACD8-C094-4255-B702-DE3BB768148F&quot;&gt;Windows Installer 2.0 Redistributable for Windows 95, 98, and Me&lt;/a&gt;&lt;/li&gt;&lt;li&gt; Download latest&lt;a href=&quot;http://downloads.activestate.com/ActivePerl/Windows/5.8/&quot;&gt;Active State Perl for Windows&lt;/a&gt; &lt;em&gt;in &lt;tt&gt;.msi&lt;/tt&gt; format&lt;/em&gt;.I used &lt;tt&gt;ActivePerl-5.8.6.811-MSWin32-x86-122208.msi&lt;/tt&gt;.&lt;/li&gt;&lt;blockquote&gt;&lt;font color=&quot;#808080&quot;&gt;&lt;b&gt;Note:&lt;/b&gt;I tried to install &lt;tt&gt;.zip&lt;/tt&gt; format, but it didn&#39;t work for me. That&#39;swhy you need first to install MSI 2.0 update.                        &lt;/font&gt;&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;Start installation:&lt;pre class=&quot;block_code&quot;&gt;$ /opt/cxoffice/bin/wine &quot;C:~WB~WINDOWS~WB~SYSTEM~WB~msiexec.exe&quot; /i ActivePerl-5.8.6.811-MSWin32-x86-122208.msi&lt;/pre&gt;After a while, it should be over.&lt;/li&gt;&lt;li&gt;Now you have perl installed in&lt;tt&gt;~/.cxoffice/dotwine/fake_windows/Perl/&lt;/tt&gt;.Try to run it:&lt;pre&gt;$ uname -aLinux llin 2.6.10-1-686 #1 Tue Jan 18 04:34:19 EST 2005 i686 GNU/Linux$ /opt/cxoffice/bin/wine &quot;c:\Perl\bin\perl.exe&quot; -v&lt;/pre&gt;You should get something like:&lt;pre&gt;This is perl, v5.8.6 built for MSWin32-x86-multi-thread(with 3 registered patches, see perl -V for more detail)Copyright 1987-2004, Larry WallBinary build 811 provided by ActiveState Corp. http://www.ActiveState.comActiveState is a division of Sophos.Built Dec 13 2004 09:52:01Perl may be copied only under the terms of either the Artistic License or theGNU General Public License, which may be found in the Perl 5 source kit.Complete documentation for Perl, including FAQ lists, should be found onthis system using `man perl&#39; or `perldoc perl&#39;.  If you have access to theInternet, point your browser at http://www.perl.org/, the Perl Home Page.&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;That&#39;s it!&lt;/em&gt;. It wasn&#39;t hard at all.&lt;/p&gt;&lt;blockquote&gt;&lt;font color=&quot;#808080&quot;&gt;&lt;b&gt;Note:&lt;/b&gt;&lt;strike&gt;There are some problems however. While calling Excel via OLE works withCrossOver, if you have Excel started it will stop responding to GUI events.So, Excel window will look like it&#39;s frozen, but your scripts should be ableto communicate with Excel anyway.&lt;/strike&gt;&lt;br/&gt;&lt;b&gt;Update:&lt;/b&gt; I was totally wrong. Adding &lt;tt&gt;$excel-&gt;{Visible} = 1;&lt;/tt&gt; fixed my problem. fvwm just doesn&#39;t know how to minimize running Excel.&lt;/font&gt;&lt;/blockquote&gt;And, now assorted list of links to get youstarted with Excel and OLE automation. TPJ article is very good introduction needed for Linux-nerd like me.&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://search.cpan.org/dist/Win32-OLE/lib/Win32/OLE/TPJ.pod&quot;&gt;The Perl Journal #10 - Win32::OLE by Jan Dubois&lt;/a&gt;&lt;li&gt;&lt;A HREF=&quot;http://aspn.activestate.com/ASPN/docs/ActivePerl-5.6/faq/Windows/ActivePerl-Winfaq12.html&quot;&gt;ActivePerl Help - Online Docs : Using OLE with Perl&lt;/A&gt;&lt;/li&gt;&lt;li&gt;[id://153486]&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>Using Perl XPath for converting Infopath XML files to Word Documents (karthik4perl)</title>
    <link>http://prlmnks.org/html/421936.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/421936.html</guid>

    <description>
        &lt;P&gt;&amp;nbsp;The other day I had filled out about 10 forms using Infopath. The problem is all Infopath documents are saved in XML and one cannot extract the contents of each XML Tag into simple text.&lt;/P&gt;&lt;P&gt;&amp;nbsp;I will explain how to extract information from XML tag and save it in a DOC format. You can then apply the same concept for the Infopath form to DOC conversion.&lt;/P&gt;&lt;P&gt;&amp;nbsp;So here goes...&lt;/P&gt;&lt;P&gt;&amp;nbsp;XPath is one of the many XML technologies you could use to traverse the XML Tree. If you access a file in your explorer, the path to your file may be in the format &quot;C:\folder1\file1.txt&quot;. XPath uses similar concept to walkthrough your XML file which can be thought as a Parent Tree containing many child nodes. &lt;/P&gt;&lt;P&gt;Lets take a very simple example. Suppose your XML file is in the following manner:&lt;/P&gt;&lt;P&gt;BOOKS.XML File&lt;BR&gt;&lt;pre class=&quot;block_code&quot;&gt;&lt;Books&gt;&lt;Book&gt; &lt;title&gt;Perl Magic&lt;/title&gt; &lt;author&gt;Karthik&lt;/author&gt; &lt;publisher&gt;ORielly&lt;/publisher&gt; &lt;price currency=&quot;Rupees&quot; value=&quot;330&quot;/&gt;&lt;/Book&gt;&lt;Book&gt; &lt;title&gt;Perl for Dummies&lt;/title&gt; &lt;author&gt;Mark&lt;/author&gt; &lt;publisher&gt;ORielly&lt;/publisher&gt; &lt;price currency=&quot;Rupees&quot; value=&quot;420&quot;/&gt;&lt;/Book&gt;&lt;/Books&gt;&lt;/pre&gt;&lt;P&gt;Now you want to extract the necessary Book Information, i.e, the &quot;Title&quot; and &quot;Author&quot; of the Books. &lt;BR&gt;From the XML file the tags &amp;lt;title&amp;gt; and &amp;lt;author&amp;gt; should be extracted.&lt;/P&gt;&lt;P&gt;Now in XPath you get the &quot;title&quot; tag&#39;s content by using the Path :&lt;/P&gt;&lt;tt class=&quot;inline_code&quot;&gt;//Books/Book/title&lt;/tt&gt;&lt;P&gt;Similarly for the &quot;author&quot; tag&#39;s content:&lt;/P&gt;&lt;tt class=&quot;inline_code&quot;&gt;//Books/Book/author&lt;/tt&gt;&lt;P&gt;Now that you know what and how extract the information, its time to use Perl.&lt;/P&gt;&lt;P&gt;The beauty of Perl is that you can materialize the idea in your mind into reality so easily. You got&lt;BR&gt;Perl modules to make your Life easy.&lt;/P&gt;&lt;P&gt;I am going to use the XPath Perl module which is part of the XML module.You use the module by coding like this&lt;/P&gt;&lt;tt class=&quot;inline_code&quot;&gt;use XML::XPath&lt;/tt&gt;&lt;P&gt;Now you need to get the BOOKS.XML file into a variable and create a new XPath object.&lt;/P&gt;&lt;pre class=&quot;block_code&quot;&gt;$file=&quot;books.xml&quot;;my $xp = XML::XPath-&gt;new(filename =&gt; $file);&lt;/pre&gt;&lt;P&gt;Open a WORD DOC file of the same name for conversion&lt;/P&gt;&lt;pre class=&quot;block_code&quot;&gt;open(INFO3, &quot;&gt;$file.doc&quot;);&lt;/pre&gt;&lt;P&gt;Print necessary information in the DOC file&lt;/P&gt;&lt;pre class=&quot;block_code&quot;&gt;print INFO3 &quot;Perl Xpath\n\n&quot;;print INFO3 &quot;BOOK INFORMATION:\n\n&quot;;&lt;/pre&gt;&lt;P&gt;&amp;nbsp;Use the find method using the XPath object and give it the path.&lt;/P&gt;&lt;tt class=&quot;inline_code&quot;&gt;//Books/Book&lt;/tt&gt;&lt;P&gt;&amp;nbsp;This will populate a Answer Node List which is used further to extract the tags &amp;lt;title&amp;gt; and &amp;lt;author&amp;gt;&lt;BR&gt;and print to the DOC file.&lt;/P&gt;&lt;tt class=&quot;inline_code&quot;&gt;$xp-&gt;find(&#39;//Books/Book&#39;)-&gt;get_nodelist&lt;/tt&gt;&lt;P&gt;The resulting Perl File(BOOKEXTRACT.PL) is given below.&lt;/P&gt;&lt;P&gt;BOOKEXTRACT.PL&lt;BR&gt;&lt;pre class=&quot;block_code&quot;&gt;use XML::XPath;  $file=&quot;books.xml&quot;; my $xp = XML::XPath-&gt;new(filename =&gt; $file);  open(INFO3, &quot;+&gt;$file.doc&quot;);  print INFO3 &quot;Perl Xpath\n\n&quot;;          print INFO3 &quot;BOOK INFORMATION:\n\n&quot;;          foreach my $book ($xp-&gt;find(&#39;//Books/Book&#39;)-&gt;get_nodelist){                 print INFO3 &quot;TITLE:&quot;;                 print INFO3 $book-&gt;find(&#39;title&#39;)-&gt;string_value.&quot;\n&quot;;                 print INFO3 &quot;AUTHOR:&quot;;                 print INFO3 $book-&gt;find(&#39;author&#39;)-&gt;string_value.&quot;\n&quot;;                 print INFO3 &quot;\n\n&quot;;          }  print &quot;Converted XML file into WORD file\n\n&quot;; print $file.&quot; WORD document generated&quot;; close(INFO3); &lt;/pre&gt;*************************CODE***********************&lt;/P&gt;&lt;P&gt;After you run the PERL Script you will be presented with a DOC file of the same name as the XML file&lt;BR&gt;with the extracted information.&lt;/P&gt;&lt;P&gt;Now that you know how to extract Tags and content into WORD DOC, you can apply the same method in the&lt;BR&gt;conversion of INFOPATH XML Files into WORD Documents.&lt;/P&gt;&lt;P&gt;Hope this helps.&lt;/P&gt;&lt;P&gt;Happy Coding.&lt;/P&gt;&lt;p&gt;&lt;small&gt;20050113 Janitored by [Corion]: Fixed formatting&lt;/small&gt;&lt;/p&gt;&lt;p&gt;&lt;small&gt;20050114 Unconsidered by [Corion]: was considered as move to Meditations (edit:14 keep:7 del:0)&lt;/small&gt;&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>Perl Babysteps 1: Your First Simple Script (webfiend)</title>
    <link>http://prlmnks.org/html/418141.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/418141.html</guid>

    <description>
        &lt;h2&gt;Introduction&lt;/h2&gt;&lt;p&gt;This page is intended to provide the non-programmer with a gentle introduction to the Perl programming language. When you are done with it, you should feel ready to learn more. You will not be an expert, but you will be able to find the information you need to go farther. Beginners and experts alike should feel free to send suggestions about how to improve this tutorial.&lt;/p&gt;&lt;a name=&quot;Installing_Perl&quot;&gt;&lt;h2&gt;Installing Perl&lt;/h2&gt;&lt;/a&gt;&lt;p&gt;It is very easy to find and install a copy of Perl for your operating system. How easy? Well, it&#39;s a single simple download, and you may already have it on your machine!&lt;/p&gt;&lt;a name=&quot;Windows&quot;&gt;&lt;h3&gt;Windows&lt;/h3&gt;&lt;/a&gt;&lt;p&gt;Well, okay. If you are using a Windows machine, you probably        &lt;em&gt;don&#39;t&lt;/em&gt; already have Perl on your machine. But it&#39;s easy to get. You even have a couple different versions to choose from.&lt;/p&gt;&lt;h4&gt;ActivePerl&lt;/h4&gt;&lt;p&gt;This is the officially blessed version of Perl for Windows. It is released by &lt;a href=&quot;http://www.activestate.com/&quot;&gt;ActiveState&lt;/a&gt;.        ActivePerl can be downloaded for free, or you can order the ActiveCD from them. It comes with a wealth of widely used third-party libraries such as Tk, LWP, and the XML bundle. Whether you choose to download or purchase, here is your best starting point:&lt;/p&gt;&lt;blockquote&gt;&lt;a href=&quot;http://www.activestate.com/Products/ActivePerl/&quot;&gt;http://www.activestate.com/Products/ActivePerl/&lt;/a&gt;&lt;/blockquote&gt;&lt;h4&gt;Perl on Cygwin&lt;/h4&gt;&lt;p&gt;On the other hand, maybe you prefer to have Windows with a touch of UNIX on top. First, I want to let you know that Perl is perfectly happy under Windows these days. But if you insist, or just happen to be curious, Perl is also available for &lt;a href=&quot;http://cygwin.com/&quot;&gt;Cygwin&lt;/a&gt;. Just rerun Cygwin&#39;s &lt;tt class=&quot;inline_code&quot;&gt;setup.exe&lt;/tt&gt; program, and make sure that &quot;Perl&quot; is        checked. Oh, and add an editor while you&#39;re at it, too. Maybe &lt;a href=&quot;http://www.vim.org/&quot;&gt;Vim&lt;/a&gt; or &lt;a href=&quot;http://gnu.org/software/emacs/&quot;&gt;Emacs&lt;/a&gt;.   &lt;/p&gt;&lt;a name=&quot;Everybody_Else&quot;&gt;&lt;h3&gt;Everybody Else&lt;/h3&gt;&lt;/a&gt;&lt;p&gt;You probably already have it, especially if you happen to be on a UNIX-based operating system such as Linux, FreeBSD, or Mac OS X. Seriously. Try the &lt;tt class=&quot;inline_code&quot;&gt;which&lt;/tt&gt; command if you don&#39;t believe me.        &lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt; $ which perl /usr/bin/perl&lt;/pre&gt;&lt;p&gt;That&#39;ll teach you to doubt me. Just kidding. If you don&#39;t have it installed, you&#39;ll get a message along the lines of &lt;tt class=&quot;inline_code&quot;&gt;perl not found in ...&lt;/tt&gt;. Double-check to see if it&#39;s on your installation media. For OS X folks, you just need to install the Developer Disk.&lt;/p&gt;&lt;a name=&quot;The_Macho_Geek_Option_Compile_From_Source&quot;&gt;&lt;h3&gt;The Macho Geek Option: Compile From Source&lt;/h3&gt;&lt;/a&gt;&lt;p&gt;Whatever operating system you are on, this is a valid choice. Still, there are a lot of options when building. It can be more than a little overwhelming. I would suggest you go with one of the available binary downloads while you&#39;re just starting out.&lt;/p&gt;&lt;a name=&quot;Creating_Perl_Programs&quot;&gt;&lt;h2&gt;Creating Perl Programs&lt;/h2&gt;&lt;/a&gt;&lt;p&gt;The tradition in programming literature is to start by creating a program that prints a simple phrase, such as &quot;Hello, World!&quot; The idea is to give you some clue how much work is involved in creating a minimal program. I, for one, am not going to argue with tradition. Not this one, at least. Type the following into your text editor:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt; # hello.pl #  - Displays a warm greeting print &quot;Hello, World!\n&quot;;&lt;/pre&gt;&lt;p&gt;Save the file as &lt;tt class=&quot;inline_code&quot;&gt;hello.pl&lt;/tt&gt;. We will run it in a few moments, but first, let&#39;s take a quick look at what we&#39;ve got so far.&lt;/p&gt;&lt;a name=&quot;Comments&quot;&gt;&lt;h3&gt;Comments&lt;/h3&gt;&lt;/a&gt;&lt;p&gt;On each line, everything from &lt;tt class=&quot;inline_code&quot;&gt;&lt;/tt&gt;# to the end of the line is a &lt;em&gt;comment&lt;/em&gt;. Perl ignores comments, so they allow you to communicate with other people who read your code. Comments are &lt;em&gt;very very good&lt;/em&gt;. When you come back to look at a complex script after a few months, you might forget what some block of code does, or why you chose one solution over another. Having the comments there help to remind you what you were intending, and generally serve to make it much easier sorting everything out.&lt;/p&gt;&lt;p&gt;I like to start all of my scripts off with a quick header to describe the purpose of the program. Here is a rough template:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt; # hello.pl #  Displays a warm greeting.&lt;/pre&gt;&lt;p&gt;All we have is the name of the file and a brief description of what the program does. That is often all that you need, especially for simple scripts like this one.&lt;/p&gt;&lt;p&gt;&lt;em&gt;NOTE&lt;/em&gt;: The official documentation system for Perl is POD, or &quot;Plain Old Documentation&quot;. It is powerful and widely used, but it is also beyond our scope for this stage of the tutorial. However, to give you a little taste of how much easier POD makes life, here is the first sentence displayed after you type the command &lt;tt class=&quot;inline_code&quot;&gt;perldoc -f print&lt;/tt&gt; at the command line:&lt;/p&gt;&lt;blockquote&gt;Prints a string or a list of strings.        &lt;/blockquote&gt;&lt;p&gt;You should read &lt;a href=&quot;/out/node/POD in 5 Minutes&quot;&gt;POD in 5 Minutes&lt;/a&gt; if you are curious to learn about how to format POD documentation for reading with the &lt;tt class=&quot;inline_code&quot;&gt;perldoc&lt;/tt&gt; command.&lt;/p&gt;&lt;p&gt;Now you would probably like to know how to actually run your program. Save the file you have been editing and switch to a command line. Make sure you are in the same directory as your script - this should be as simple as &lt;tt class=&quot;inline_code&quot;&gt;cd project_directory&lt;/tt&gt;. Once you are in the right place, type the following into the command line:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt; $ perl hello.pl Hello, World! $&lt;/pre&gt;&lt;p&gt;Oh, what was the &quot;\n&quot; at the end of the string for? That is a fair question. It&#39;s a special code for the newline character. What&#39;s the newline character do? It&#39;s easier to show you what happens when you &lt;em&gt;don&#39;t&lt;/em&gt; have it:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt; print &quot;Hello, World!&quot;;&lt;/pre&gt;&lt;p&gt;Save it and run it.&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt; $ perl hello.pl Hello, World!$&lt;/pre&gt;&lt;p&gt;Adding a newline character in the string tells Perl that you want to print a new line. Now do you see?&lt;/p&gt;&lt;p&gt;All this is kind of cool, but it would be nice to customize it a little bit. Maybe we could change the program so that it says &quot;Hello&quot; to us personally.&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt; # hello.pl #  Displays a warm greeting. my $name = &quot;Brian&quot;; print &quot;Hello, $name!\n&quot;;&lt;/pre&gt;&lt;p&gt;Now you might notice the semicolon at the end of each line. What? You noticed them before? Well, you&#39;re quicker than me. Perl recognizes the semicolon as the marker which ends one statement. So each statement must be terminated by a semicolon. Putting them on separate lines like that is something that Perl doesn&#39;t care about, but you might lose friends if you tried to put everything on one line.&lt;/p&gt;&lt;p&gt;Now -- what? &lt;em&gt;Another&lt;/em&gt; question? Okay, go ahead. What&#39;s that &lt;tt class=&quot;inline_code&quot;&gt;my&lt;/tt&gt; doing? We use the word &lt;tt class=&quot;inline_code&quot;&gt;my&lt;/tt&gt; to declare variables. Declaration is         when we tell Perl that we have a variable we plan on using. The language doesn&#39;t require declaration, but it is good form, and you will find your code easier to debug later on as you learn more about clean programming.&lt;/p&gt;&lt;p&gt;What&#39;s a variable? We&#39;ll get to that in a second. I&#39;m impatient to see a running program! Save the file, and run it again.&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt; $ perl hello.pl Hello, Brian! $&lt;/pre&gt;&lt;p&gt;There, I feel better. Let&#39;s move on to talking about variables.&lt;/p&gt;&lt;a name=&quot;Variables&quot;&gt;&lt;h3&gt;Variables&lt;/h3&gt;&lt;/a&gt;&lt;p&gt;We stored the string &quot;Brian&quot; in the variable &lt;tt class=&quot;inline_code&quot;&gt;name&lt;/tt&gt;. A &lt;em&gt;variable&lt;/em&gt; is basically just something you want the computer to remember so that you can get to it when you want it later. You can get a lot morecomplicated than that if you want, and a lot of programmers do. However, this definition should hold us over for a long time.&lt;/p&gt;&lt;p&gt;The &quot;&lt;tt class=&quot;inline_code&quot;&gt;$&lt;/tt&gt;&quot; symbol at the beginning tells Perl what kind of information this variable holds. Perl basically has two kinds of variables: &lt;/p&gt;&lt;ol&gt;  &lt;li&gt;Individual things like strings and numbers&lt;/li&gt;  &lt;li&gt;Collections of things like lists and dictionaries&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;When you start digging in, you will see how broad of a generalization I&#39;ve just made. Still, I think that this will last us until the end of this article, and the basic idea holds true for a &lt;em&gt;lot&lt;/em&gt; of Perl programming.&lt;/p&gt;&lt;p&gt;Anyways. Individual things are also called &lt;em&gt;scalars&lt;/em&gt; by people who think that you don&#39;t have enough things to remember. Ah well, we&#39;ll get used to it. To their credit, &quot;scalar&quot; &lt;em&gt;is&lt;/em&gt; a shorter term than &quot;individual thing&quot;. Perl makes it easy to recognize a scalar, by making you prefix all scalar variables with a dollar sign. So &lt;tt class=&quot;inline_code&quot;&gt;$name&lt;/tt&gt; is &quot;the scalar variable name&quot;, or even &quot;the individual thing called name&quot;. Eventually many Perl hackers end up calling it &quot;dollar name&quot;.&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt; my $name = &quot;Brian&quot;; # My scalar variable called &#39;name&#39; has the value &quot;Brian&quot;&lt;/pre&gt;&lt;p&gt;Having a program that displays the exact same message every time you run is nice when it comes to being consistent, but not so entertaining as a program. &quot;What does it do?&quot; &quot;It prints out my name.&quot; &quot;Oh.&quot; See? &lt;em&gt;Boring&lt;/em&gt;. Let&#39;s make things a little more interesting. We could change the value of &lt;tt class=&quot;inline_code&quot;&gt;name&lt;/tt&gt; in the code, but it might be a little tiresome to do this before showing it to each new person. How about making the program ask for a name? User interaction - a neat idea.&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt; print &quot;What is your name? &quot;; my $name = &lt;STDIN&gt;; print &quot;Hello, $name!\n&quot;;&lt;/pre&gt;&lt;p&gt;We only made one small change, but I&#39;ll admit that there&#39;s a lot going on with that one change. Here&#39;s the short version:&lt;/p&gt;&lt;blockquote&gt;&lt;tt class=&quot;inline_code&quot;&gt;&lt;STDIN&gt;&lt;/tt&gt; gets input from the user that you can save in a variable.&lt;/blockquote&gt;&lt;p&gt;There&#39;s a long version. Feel free to skip it if you just want to get on with it. The long version works out like this:&lt;/p&gt;&lt;blockquote&gt;The scalar &lt;tt class=&quot;inline_code&quot;&gt;$name&lt;/tt&gt; is assigned the value of &amp;lt;STDIN&amp;GT; . &lt;tt class=&quot;inline_code&quot;&gt;&lt;...&gt;&lt;/tt&gt; tells Perl that we want it to read a &lt;em&gt;filehandle&lt;/em&gt; and hand the results back to us. A &lt;em&gt;filehandle&lt;/em&gt; is a source of information. It could be an open file, but in this case it is &lt;tt class=&quot;inline_code&quot;&gt;STDIN&lt;/tt&gt;. &lt;em&gt;&lt;tt class=&quot;inline_code&quot;&gt;STDIN&lt;/tt&gt;&lt;/em&gt; is the &lt;em&gt;standard input stream&lt;/em&gt; - geek talk for &quot;wherever we expect user input to be coming from&quot;. Most of the time, &lt;tt class=&quot;inline_code&quot;&gt;STDIN&lt;/tt&gt; just means &quot;keys the user enters from the keyboard&quot;. The result of reading from the filehandle &lt;em&gt;(in this case, &lt;tt class=&quot;inline_code&quot;&gt;STDIN&lt;/tt&gt;, which is in this case the text you entered from the keyboard)&lt;/em&gt; is stored in &lt;tt class=&quot;inline_code&quot;&gt;$name&lt;/tt&gt;.&lt;/blockquote&gt;&lt;p&gt;There&#39;s a really long version, but I&#39;m getting bored so we&#39;ll skip it for now.&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt; $ perl hello.pl What is your name? Brian Hello, Brian ! $&lt;/pre&gt;&lt;p&gt;Hey, what happened? The exclamation is all the way on the next line!&lt;/p&gt;&lt;p&gt;Calm down. Everything is going to be okay. Perl just counts the &lt;tt class=&quot;inline_code&quot;&gt;ENTER&lt;/tt&gt; key at the end as a part of the input, and &lt;tt class=&quot;inline_code&quot;&gt;ENTER&lt;/tt&gt; prints out as a newline &lt;em&gt;(&#39;\n&#39; if you&#39;ve been paying attention)&lt;/em&gt;. Counting the newline is fine for reading text from a file, but it&#39;s a little inconvenient when you are handling input from the keyboard. Fortunately, there&#39;s the &lt;tt class=&quot;inline_code&quot;&gt;chomp&lt;/tt&gt; function. What&#39;s it do? Let&#39;s ask &lt;tt class=&quot;inline_code&quot;&gt;perldoc -f chomp&lt;/tt&gt;. On second thought, let&#39;s not. You can goright ahead, but I just did, and discovered that the docs for &lt;tt class=&quot;inline_code&quot;&gt;chomp&lt;/tt&gt; are a little dense for today. Let&#39;s try mine:&lt;/p&gt;&lt;blockquote&gt;&lt;tt class=&quot;inline_code&quot;&gt;chomp&lt;/tt&gt; removes the last character from a string, &lt;em&gt;but only if that character is whitespace or a newline&lt;/em&gt;.&lt;/blockquote&gt;&lt;p&gt;Let&#39;s give it a try.&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt; print &quot;What is your name? &quot;; my $name = &lt;STDIN&gt;; chomp($name); print &quot;Hello, $name!\n&quot;;&lt;/pre&gt;&lt;p&gt;You already know what &lt;tt class=&quot;inline_code&quot;&gt;chomp&lt;/tt&gt; does, so running this script shouldn&#39;t provide any surprises:&lt;/p&gt;&lt;pre class=&quot;block_code&quot;&gt; $ perl hello.pl What is your name? Brian Hello, Brian! $&lt;/pre&gt;&lt;p&gt;... and we&#39;re done!&lt;/p&gt;&lt;a name=&quot;Conclusion&quot;&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;/a&gt;&lt;p&gt;Nice work! You have begun to learn Perl by writing a complete program which gets input from a user and prints output including a modified version of their input. Stop for a minute and think about it. Yes, there is much more to learn, but you have dipped your toes into the pool. Now you can go out there and start learning about the huge and wild world of Perl programming.&lt;/p&gt;&lt;a name=&quot;Additional_Resources&quot; id=&quot;Additional_Resources&quot;&gt;&lt;h3&gt;Additional Resources&lt;/h3&gt;&lt;/a&gt;&lt;p&gt;Here are a few links to resources that you can use while learning about Perl and how to use it for your own nefarious purposes.&lt;/p&gt;&lt;ul&gt;  &lt;li&gt;[Tutorials]&lt;/li&gt;  &lt;li&gt;[Where and how to start learning Perl]&lt;/li&gt;  &lt;li&gt;&lt;a href=&quot;http://learn.perl.org&quot;&gt;http://learn.perl.org&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href=&quot;http://www.perl.com/&quot;&gt;http://www.perl.com/&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href=&quot;http://perl.oreilly.com/&quot;&gt;http://perl.oreilly.com/&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href=&quot;http://perldoc.perl.org/&quot;&gt;http://perldoc.perl.org/&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href=&quot;http://www.oreilly.com/catalog/lperl3/&quot;&gt;Learning Perl&lt;/a&gt;&lt;/a&gt; is &lt;em&gt;the&lt;/em&gt; book for the person who is just starting out with programming in Perl.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;There are a &lt;em&gt;lot&lt;/em&gt; more, but I can&#39;t recall many of the links right now. I may put them up as time goes on.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt;&lt;em&gt;(30 Dec 2004)&lt;/em&gt;&lt;br /&gt;Removed an aside about complicated script headers, since [Juerd] pointed out that Perldoc is a better choice for such information, and [Anonymous Monk] helped me realize that it may be a bit much to expect a total newbie to know when the extended information becomes necessary. If you want to know what that extended header looked like, check the first reply from [Juerd]. He was gracious enough to reproduce it in its entirety while making a much better suggestion. I also went ahead and did some formatting adjustments (replacing PRE blocks with CODE blocks).&lt;/p&gt;&lt;p&gt;Threw in some suggested links from [kutsu], too.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt;&lt;em&gt;(26 Jan 2005)&lt;/em&gt;&lt;br /&gt;Fixed several typographical errors pointed out by [erix]&lt;/p&gt;&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt;&lt;em&gt;(9 May 2006)&lt;/em&gt;&lt;br /&gt;Fixed a few markup issues and added link to http://perldoc.perl.org/ -- thanks [jdporter]&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>Enabling GUI Debugging under Mod_Perl (mkirank)</title>
    <link>http://prlmnks.org/html/412121.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/412121.html</guid>

    <description>
        Greetings &lt;br&gt;   I Did the following to Enable GUI Debugging of Mod_Perl (Apache::Registry) scripts (I got this Information from different places ) ,&lt;br&gt; I have documented the steps followed and want to put it under the appropriate section &lt;b&gt;(Suggest appropriate section) &lt;/b&gt;in perlmonks ,&lt;br&gt;    This is my first attempt to writing a Setup Guide so am seeking the wise monks Inputs on the same.   &lt;br&gt;   Please let me know your Feedback/Opinions and any suggestions   &lt;br&gt;&lt;br&gt;   &lt;h2&gt; Steps Followed &lt;/h2&gt;&lt;br&gt;&lt;b&gt; Installed the following packages from CPAN&lt;/b&gt;&lt;br&gt;1.Tk Graphical User Interface ToolKit from CPAN (Tk-804.027.tar)&lt;br&gt;2. Installed the Apache-DB-0.09&lt;br&gt;3. Installed the Devel-ptkdb-1.1091.tar.gz&lt;br&gt;&lt;br&gt;&lt;b&gt; Open the Apache::DB.pm file and change &lt;/b&gt;&lt;br&gt;    #require &#39;Apache/perl5db.pl&#39;; Comment this line&lt;br&gt;   require &#39;Devel/ptkdb.pm&#39;;&lt;br&gt;&lt;br&gt;&lt;h3&gt;Save the below code as file Db.patch &lt;/h3&gt;&lt;br&gt;&lt;pre class=&quot;block_code&quot;&gt;#################################################################--- DB.pm2003/07/23 16:59:071.1+++ DB.pm2003/07/23 17:03:29@@ -39,6 +39,34 @@     return 0; } ++sub ptkdb ($$) {+    my ($class,$r) = @_;++    init();++    # need to have a list of authorized remote hosts+    $ENV{DISPLAY} = $r-&gt;get_remote_host.&#39;:0.0&#39;;+    $DB::connection_refused = 0;  # try try again+    require &#39;Devel/ptkdb.pm&#39;;+    $DB::single = 1;+# bug workaround?  Pressing &quot;Return&quot; button at toplevel makes ptkdb hang.+    $DB::subroutine_depth = 0 ;+    $DB::step_over_depth = -1 ;++    if (ref $r) {+        $SIG{INT} = \&amp;DB::dbint_handler;+        $r-&gt;register_cleanup(sub {+            $SIG{INT} = \&amp;DB::ApacheSIGINT();+            $DB::single = 0; # do not debug during withdraw+            $DB::window-&gt;close_ptkdb_window;+        });+    }++    return 0;+}++ 1; __END__################################################################# &lt;/pre&gt;&lt;br&gt;&lt;h3&gt; Save the below code as file Ptkdb.patch &lt;/h3&gt;&lt;br&gt;&lt;pre class=&quot;block_code&quot;&gt;#################################################################--- ptkdb.pm2003/07/23 17:05:201.1+++ ptkdb.pm2003/07/23 17:51:09@@ -1105,8 +1105,21 @@    # Main Window   -+eval {   $self-&gt;{main_window} = MainWindow-&gt;new() ;+};+if ($@) {+  my $err = $@;+  my $r = eval { Apache-&gt;request };  # check if running under mod_perl+  undef $@;+  if ($r &amp;&amp; $err =~ m/Xlib: connection .*? refused|Xlib: Client is not authorized|couldn&#39;t connect to display/) {+$DB::connection_refused = 1;+  $self-&gt;{main_window} = undef;+warn($err);  # log the problem+        return;+  } +  die $err;+}   $self-&gt;{main_window}-&gt;geometry($ENV{&#39;PTKDB_GEOMETRY&#39;} || &quot;800x600&quot;) ;    $self-&gt;setup_options() ; # must be done after MainWindow and before other frames are setup@@ -1237,8 +1250,9 @@    $DB::window-&gt;{&#39;event&#39;} = &#39;run&#39; ;   $self-&gt;{current_file} = &quot;&quot; ; # force a file reset-  $self-&gt;{&#39;main_window&#39;}-&gt;destroy ;+  $self-&gt;{&#39;main_window&#39;}-&gt;destroy if $self-&gt;{&#39;main_window&#39;};   $self-&gt;{&#39;main_window&#39;} = undef ;+  $DB::connection_refused = undef;  # allow another try }  sub setup_menu_bar {@@ -4048,7 +4062,12 @@      $^W = $saveW ;    unless( $DB::ptkdb::isInitialized ) {-     return if( $filename ne $0 ) ; # not in our target file+     if ( $filename ne $0 ) { # not in our target file+        # check if running under mod_perl+my $r = eval { Apache-&gt;request };+undef $@;+return unless $r;+     }      &amp;DB::Initialize($filename) ;    } @@ -4063,6 +4082,11 @@      return ;    } +   if ( $DB::connection_refused ) {  # X to remote host failed+     $@ = $DB::save_err ;+     return ;+   }+  $DB::window-&gt;setup_main_window() unless $DB::window-&gt;{&#39;main_window&#39;} ;   $DB::window-&gt;EnterActions() ;#################################################################&lt;/pre&gt;&lt;h4&gt; Install the DB.pm Patch &lt;/h4&gt;&lt;br&gt;Note  &lt;b&gt;Find the path of DB.pm and ptkdb.pm (on Linux You can use Locate  command) &lt;/b&gt; &lt;br&gt;patch &lt;PATH ON SYSTEM&gt;/Apache/DB.pm &lt; Db.patch&lt;br&gt;Install the ptkdb patch &lt;br&gt;patch &lt;PATH ON SYSTEM&gt;/Devel/ptkdb.pm &lt; Ptkdb.patch&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;Add the Following Lines in Httpd.conf&lt;/b&gt;&lt;br&gt;&lt;pre class=&quot;block_code&quot;&gt;&lt;IfDefine PERLDB&gt;    &lt;Perl&gt;      use Apache::DB ();      Apache::DB-&gt;init;    &lt;/Perl&gt;    &lt;Location /&gt;      PerlFixupHandler  Apache::DB-&gt;ptkdb    &lt;/Location&gt;&lt;/IfDefine&gt;&lt;/pre&gt;&lt;br&gt;Start the Httpd with the Following Command (this starts apache in a Single mode)&lt;br&gt;&lt;b&gt; /usr/local/apache/bin/httpd  -X -D PERLDB &lt;/b&gt;&lt;br&gt;&lt;br&gt;Enable the X-Windows (there are some security considerations ..man xhost for more details.) xhost +&lt;br&gt;When a request is sent the GUI pops up and we can go through the script (for the scripts that we run under Apache::Registry )&lt;br&gt; We need to step in  on the below Line below&lt;br&gt;&lt;pre class=&quot;block_code&quot;&gt;  eval &amp; {$cv}($r, @_) } if $r-&gt;seqno;&lt;/pre&gt;&lt;br&gt;&lt;b&gt;If your server is Linux and u are working on Windows you can do the same by using xterm &lt;/b&gt;&lt;br&gt;&lt;h4&gt; Install cygwin &lt;/h4&gt;Open cygwin &lt;br&gt;export DISPLAY=localhost:0.0&lt;br&gt;X -multiwindow &amp;&lt;br&gt;xhost +&lt;br&gt;xterm -display localhost:0 &amp;&lt;br&gt;ssh -X -l root &lt;LINUX SERVER&gt;&lt;br&gt;export DISPLAY=localhost:0.0&lt;br&gt;xhost +&lt;br&gt;&lt;p&gt;&lt;small&gt;2004-12-03 Janitored by [Arunbear] - added readmore tags, as per Monastery [id://17558|guidelines]&lt;/small&gt;&lt;/p&gt;&lt;p&gt;&lt;small&gt;&lt;strong&gt;Updated&lt;/strong&gt; [Steve_p] - moved to Tutorials per consideration&lt;/small&gt;&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>Perl documentation documentation (brian_d_foy)</title>
    <link>http://prlmnks.org/html/408254.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/408254.html</guid>

    <description>
        &lt;p&gt;I had too much free time today, so I created a new perl man page.  It&#39;s been surprisingly useful for other people already.&lt;/p&gt;&lt;h2&gt;&lt;a name=&quot;name&quot;&gt;NAME&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;perldocs - Perl documentation documentation&lt;/p&gt;&lt;hr /&gt;&lt;h2&gt;&lt;a name=&quot;synopsis&quot;&gt;SYNOPSIS&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;This documents the perl documentation&lt;/p&gt;&lt;hr /&gt;&lt;h2&gt;&lt;a name=&quot;description&quot;&gt;DESCRIPTION&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;If you have perl, you should have the documentation.&lt;/p&gt;&lt;p&gt;Before perl existed, it had no documention.  Then version 1came along and that changed.  As I write this, perl is up toversion 5.8 and it has over a thousand pages ofdocumentation that comes with perl itself.&lt;/p&gt;&lt;p&gt;I generally advise people to read the documentation first,but it&#39;s too late for that in most cases, and even if youdid, it would take you a long time to finish.  The trick isto know where to look to get what you need.&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;reading_the_frickin__manual&quot;&gt;Reading the Frickin&#39; Manual&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The perl manual pages are on your system somewhere (unlessyou have Mac OS X, it seems: stay tuned for updates).  Youcan use the &lt;tt class=&quot;inline_code&quot;&gt;perldoc&lt;/tt&gt; command line program to read aparticular page. If you want to find out how to use it, usethe perldoc command to read its documentation.&lt;/p&gt;&lt;pre&gt;        perldoc perldoc&lt;/pre&gt;&lt;p&gt;Any time you want to read a perl manual page, just tellperldoc to display that page.  If I want to read &lt;tt class=&quot;inline_code&quot;&gt;perltoc&lt;/tt&gt;, Iuse &lt;tt class=&quot;inline_code&quot;&gt;perldoc&lt;/tt&gt;.&lt;/p&gt;&lt;pre&gt;        perldoc perltoc&lt;/pre&gt;&lt;p&gt;Your system may also have the documentation in otherformats, such as HTML or Windows Help files.&lt;/p&gt;&lt;p&gt;You can also read the perl docs on the web: &lt;a href=&quot;/out/http/?url=perldoc.perl.org%2F&quot;&gt;http://perldoc.perl.org/&lt;/a&gt;.&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;enough_pod_to_be_dangerous&quot;&gt;Enough POD to be dangerous&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;POD is ``Plain old documentation&#39;&#39;.  It&#39;s a minimal plain text formatthat most perlers use to write things.  Its format is explained in&lt;tt class=&quot;inline_code&quot;&gt;perlpod&lt;/tt&gt;.&lt;/p&gt;&lt;pre&gt;        perldoc perlpod&lt;/pre&gt;&lt;p&gt;You can look at the POD source with &lt;tt class=&quot;inline_code&quot;&gt;perldoc&lt;/tt&gt;&#39;s -m switch.&lt;/p&gt;&lt;pre&gt;        perldoc -m perlpod&lt;/pre&gt;&lt;p&gt;You can check your (or somebody else&#39;s) POD with &lt;tt class=&quot;inline_code&quot;&gt;podchecker&lt;/tt&gt;or the Test::Pod module.&lt;/p&gt;&lt;p&gt;You can convert POD to other formats, including LaTeX, HTML,and text. Look for the pod2latex, pod2html, and pod2text.You need to give it the file name to convert, which you canget with &lt;tt class=&quot;inline_code&quot;&gt;perldoc&lt;/tt&gt;&#39;s -l switch.&lt;/p&gt;&lt;pre&gt;        pod2html `perldoc -l perl` &amp;gt; perl.html&lt;/pre&gt;&lt;h3&gt;&lt;a name=&quot;perltoc&quot;&gt;perltoc&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;If you don&#39;t know which page you need to read, start with &lt;tt class=&quot;inline_code&quot;&gt;perltoc&lt;/tt&gt;,which is the table of contents for the rest of the core perldocumentation.&lt;/p&gt;&lt;pre&gt;        perldoc perltoc&lt;/pre&gt;&lt;h3&gt;&lt;a name=&quot;perlfaq&quot;&gt;perlfaq&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Even if you are one in a million, that leaves 5,000 peoplejust like you, and if only 1 in a thousand use perl, that&#39;sstill 5 perl programmers just like you.  Every one of those5 people have already asked your question, twice.  Theanswer might be in &lt;tt class=&quot;inline_code&quot;&gt;perlfaq&lt;/tt&gt; somewhere.&lt;/p&gt;&lt;p&gt;There are nine &lt;tt class=&quot;inline_code&quot;&gt;perlfaq&lt;/tt&gt; pages, broken into broadcategories.  &lt;tt class=&quot;inline_code&quot;&gt;perlfaq&lt;/tt&gt; is a table of contents.&lt;/p&gt;&lt;p&gt;You can search the &lt;tt class=&quot;inline_code&quot;&gt;perlfaq&lt;/tt&gt; pages with &lt;tt class=&quot;inline_code&quot;&gt;perldoc&lt;/tt&gt;&#39;s -qswitch.&lt;/p&gt;&lt;pre&gt;        perldoc -q perldoc&lt;/pre&gt;&lt;p&gt;You can read the perlfaq online at &lt;a href=&quot;/out/http/?url=perldoc.perl.org%2Fperlfaq.html&quot;&gt;http://perldoc.perl.org/perlfaq.html&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Parts of the &lt;tt class=&quot;inline_code&quot;&gt;perlfaq&lt;/tt&gt; are regularly posted to the usenet groupcomp.lang.perl.misc .&lt;/p&gt;&lt;p&gt;If you want to see the latest version of the perlfaq, you cancheck out the sources from CVS. &lt;a href=&quot;/out/http/?url=cvs.perl.org%2Fviewcvs%2Fcvs-public%2Fperlfaq%2F&quot;&gt;http://cvs.perl.org/viewcvs/cvs-public/perlfaq/&lt;/a&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;perlfunc&quot;&gt;perlfunc&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;tt class=&quot;inline_code&quot;&gt;perlfunc&lt;/tt&gt; lists the documentation for each perl function, and althoughyou should read it through at least once in your life, you can read thedocumentation for a single function with &lt;tt class=&quot;inline_code&quot;&gt;perldoc&lt;/tt&gt;&#39;s -f switch.&lt;/p&gt;&lt;pre&gt;        perldoc -f localtime&lt;/pre&gt;&lt;h3&gt;&lt;a name=&quot;modules&quot;&gt;Modules&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Use the &lt;tt class=&quot;inline_code&quot;&gt;perldoc&lt;/tt&gt; command to read the documentation forinstalled modules.&lt;/p&gt;&lt;pre&gt;        perldoc Module::Starter&lt;/pre&gt;&lt;h3&gt;&lt;a name=&quot;cpan_search&quot;&gt;CPAN Search&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Look on CPAN Search, &lt;a href=&quot;/out/http/?url=search.cpan.org&quot;&gt;http://search.cpan.org&lt;/a&gt;, fordocumentation on modules that you haven&#39;t installed.&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;randal_s_columns&quot;&gt;Randal&#39;s columns&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Randal has spent way too much time writing about Perl for itall to go to waste.  Most of his columns are availableonline. &lt;a href=&quot;/out/http/?url=www.stonehenge.com%2Fmerlyn%2Fcolumns.html&quot;&gt;http://www.stonehenge.com/merlyn/columns.html&lt;/a&gt;.&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;google&quot;&gt;Google&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Learn to use Google to find things.  Use &lt;tt class=&quot;inline_code&quot;&gt;perl&lt;/tt&gt; as a keyword.You only think this is obvious, but read the questions inusenet groups or on Perlmonks for a while to find outjust how many people can&#39;t use a search engine.&lt;/p&gt;&lt;p&gt;For instance, you can limit your search to a particular sitewith in a Google search.  This query limits itself to perldoc.perl.org&lt;/p&gt;&lt;pre&gt;        site:perldoc.perl.org CGI&lt;/pre&gt;&lt;p&gt;You can search Randal&#39;s articles for ``deep copy&#39;&#39;,&lt;/p&gt;&lt;pre&gt;        site:www.stonehenge.com &amp;quot;deep copy&amp;quot;&lt;/pre&gt;&lt;p&gt;or search Perlmonks for @ISA&lt;/p&gt;&lt;pre&gt;        site:perlmonks.thepen.com @ISA&lt;/pre&gt;&lt;p&gt;or search CPAN Search for ``pop3 ssl&#39;&#39;&lt;/p&gt;&lt;pre&gt;        site:search.cpan.org POP3 ssl&lt;/pre&gt;&lt;h3&gt;&lt;a name=&quot;the_camel&quot;&gt;The Camel&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;/out/http/?url=www.oreilly.com%2Fcatalog%2Fpperl3%2F&quot;&gt;http://www.oreilly.com/catalog/pperl3/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;You don&#39;t have to buy ``Programming Perl&#39;&#39;, also known as theCamel book, but you also don&#39;t have to have any free timeeither.  It&#39;s your choice.  Every copy you buy supports starvingchildren in Mountain View.&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;the_llama&quot;&gt;The Llama&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;/out/http/?url=www.oreilly.com%2Fcatalog%2Flearnperl4%2F&quot;&gt;http://www.oreilly.com/catalog/learnperl4/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The Llama book is ``Learning Perl&#39;&#39;.  You don&#39;t have to learnPerl, but it helps.  You&#39;d be surprised how many people tryto get by without learning Perl.&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;the_ram&quot;&gt;The Ram&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;/out/http/?url=www.oreilly.com%2Fcatalog%2Fperlckbk2%2Findex.html&quot;&gt;http://www.oreilly.com/catalog/perlckbk2/index.html&lt;/a&gt;&lt;/p&gt;&lt;p&gt;A lot of people like ``The Perl Cookbook&#39;&#39;.  When you aren&#39;t readingits hundreds of pages for Perl recipes, it makes a darnedgood paperweight or a doorstop.&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;comprehensive_perl_archive_network__cpan_&quot;&gt;Comprehensive Perl Archive Network (CPAN)&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Most of what you think of CPAN probably isn&#39;t: it&#39;s just the archive.CPAN Search, module uploads, CPAN.pm, and other things are not CPAN.&lt;/p&gt;&lt;p&gt;CPAN has its own FAQ that explains it all. &lt;a href=&quot;/out/http/?url=www.cpan.org%2Fmisc%2Fcpan-faq.html&quot;&gt;http://www.cpan.org/misc/cpan-faq.html&lt;/a&gt;&lt;/p&gt;&lt;h3&gt;&lt;a name=&quot;perl_authors_upload_server__pause_&quot;&gt;Perl Authors Upload Server (PAUSE)&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;PAUSE is the author interface to CPAN, and it has its own documentation. &lt;a href=&quot;/out/http/?url=pause.perl.org%2Fpause%2Fquery%3FACTION%3Dpause_04about&quot;&gt;http://pause.perl.org/pause/query&lt;/a&gt;.&lt;/p&gt;&lt;!-- Node text goes above. Div tags should contain sig only --&gt;&lt;div class=&quot;pmsig&quot;&gt;&lt;div class=&quot;pmsig-366986&quot;&gt;-- &lt;br /&gt;brian d foy &lt;bdfoy@cpan.org&gt;&lt;/div&gt;&lt;/div&gt;
    </description>
</item>

        

<item>
    <title>quotes in Perl (apotheon)</title>
    <link>http://prlmnks.org/html/401006.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/401006.html</guid>

    <description>
        Quotation marks are fairly ubiquitous in Perl, as in most programming languages.  Different methods of quoting exist, and each has different uses and a different set of behaviors associated with it.&lt;br /&gt;&lt;br /&gt;This document is intended as a treatment of the subject of delimiting strings &amp;mdash; &quot;quoting&quot;.  I try to keep it from devolving into lengthy digressions on tangential topics, such as escape characters and interpolation.  Such topics do tie in with the use of such delimiters, however, and must to some degree be addressed.  Further information can be found at [http://perldoc.perl.org/perlop.html|perlop].&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;hr /&gt;&lt;/center&gt;&lt;h3&gt;single-quotes&lt;/h3&gt;Single quotation marks are used to enclose data you want taken literally.  Just as the &amp;lt;code&amp;gt;&amp;lt;/code&amp;gt; tags here at the Monastery make all text they enclose literally rendered, whitespace and all, so too does a set of single-quotes in Perl ensure that what they enclose is used literally:&lt;br /&gt;&lt;blockquote&gt;&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perl -wuse strict;my $foo;my $bar;$foo = 7;$bar = &#39;it is worth $foo&#39;;print $bar;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;This example, when run, produces the following:&lt;br /&gt;&lt;blockquote&gt;&lt;tt class=&quot;inline_code&quot;&gt;it is worth $foo&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;hr /&gt;&lt;/center&gt;&lt;h3&gt;double-quotes&lt;/h3&gt;Double quotation marks are used to enclose data that needs to be interpolated before processing.  That means that escaped characters and variables aren&#39;t simply literally inserted into later operations, but are evaluated on the spot.  Escape characters can be used to insert newlines, tabs, and other special characters into a string, for instance.  The values, or contents, of variables are used in double-quoted strings, rather than the names of variables.  For instance:&lt;br /&gt;&lt;blockquote&gt;&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perl -wuse strict;my $foo;my $bar;$foo = 7;$bar = &quot;it is worth $foo&quot;;print $bar;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;This example, when run, produces the following:&lt;br /&gt;&lt;blockquote&gt;&lt;tt class=&quot;inline_code&quot;&gt;it is worth 7&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;Double-quotes interpolate scalar and array variables, but not hashes.  On the other hand, you can use double-quotes to interpolate slices of both arrays and hashes.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;hr /&gt;&lt;/center&gt;&lt;h3&gt;escape characters&lt;/h3&gt;The interpolating effects of double-quotes creates a necessity of using escaped characters to reproduce characters within a string that would be displayed literally within single-quotes, however.  For instance, to add quotes to the above-printed string in the double-quote example, you would have to do something like this:&lt;br /&gt;&lt;blockquote&gt;&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perl -wuse strict;my $foo;my $bar;$foo = 7;$bar = &quot;it is \&quot;worth\&quot; $foo&quot;;print $bar;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;The backslash &quot;escapes&quot; the quotation mark that follows it, so that running the above produces the following:&lt;br/&gt;&lt;blockquote&gt;&lt;tt class=&quot;inline_code&quot;&gt;it is &quot;worth&quot; 7&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;An exception to the literal interpretation behavior in the use of single-quotes is when you wish to include single-quotes inside the string.  In that case, you must escape the single-quotes you want inside the string so the Perl compiler can discern between them and the single-quotes that delimit the string:&lt;br /&gt;&lt;blockquote&gt;&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perl -wuse strict;my $foo;my $bar;$foo = 7;$bar = &#39;it is \&#39;worth\&#39; $foo&#39;;print $bar;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;This example, when run, produces the following:&lt;br /&gt;&lt;blockquote&gt;&lt;tt class=&quot;inline_code&quot;&gt;it is &#39;worth&#39; $foo&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;In any interpolating quotation scheme, such as double-quotes (or &lt;tt class=&quot;inline_code&quot;&gt;qq&lt;/tt&gt; and interpolating uses of &lt;tt class=&quot;inline_code&quot;&gt;&lt;&lt;&lt;/tt&gt;, as described below), @ and $ characters must be escaped when you want them used literally.  If they are not, they will be treated by the Perl compiler as indicators of variable names.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;hr /&gt;&lt;/center&gt;&lt;h3&gt;quoting without quotes&lt;/h3&gt;In Perl, you can use methods other than quotation marks to &quot;quote&quot; a string.  This functionality makes using strings that contain quotation marks much easier sometimes, since those quotation marks no longer need to be escaped.  There are three simple methods of doing this with the letter q.&lt;br /&gt;&lt;br /&gt;In the following three sections, on the subjects of &lt;tt class=&quot;inline_code&quot;&gt;q&lt;/tt&gt;, &lt;tt class=&quot;inline_code&quot;&gt;qq&lt;/tt&gt;, and &lt;tt class=&quot;inline_code&quot;&gt;qw&lt;/tt&gt; notation, I refer exclusively to the use of parentheses as delimiters.  Other delimiters can be used, however, which allows you to avoid having to escape the characters you choose to use as delimiters if you must also include instances of them in your string.  For instance, instead of using parentheses, you could also use brackets ( &lt;tt class=&quot;inline_code&quot;&gt;[ ]&lt;/tt&gt; ), braces ( &lt;tt class=&quot;inline_code&quot;&gt;{ }&lt;/tt&gt; ), asterisks ( &lt;tt class=&quot;inline_code&quot;&gt;* *&lt;/tt&gt; ), and (almost?) any other characters other than whitespace.  It&#39;s worth noting that in the case of an alphanumeric character there must be a space between the &lt;tt class=&quot;inline_code&quot;&gt;q&lt;/tt&gt; (or &lt;tt class=&quot;inline_code&quot;&gt;qw&lt;/tt&gt;, or &lt;tt class=&quot;inline_code&quot;&gt;qq&lt;/tt&gt;).&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;hr /&gt;&lt;/center&gt;&lt;h3&gt;q&lt;/h3&gt;The first way to quote without quotes is to use &lt;tt class=&quot;inline_code&quot;&gt;q()&lt;/tt&gt; notation.  Instead of using quotation marks, you would use parentheses with a &lt;tt class=&quot;inline_code&quot;&gt;q&lt;/tt&gt; preceding them:&lt;br /&gt;&lt;blockquote&gt;&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perl -wuse strict;my $foo;my $bar;$foo = 7;$bar = q(it is &#39;worth&#39; $foo);print $bar;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;This example, when run, produces the following:&lt;br /&gt;&lt;blockquote&gt;&lt;tt class=&quot;inline_code&quot;&gt;it is &#39;worth&#39; $foo&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;The &lt;tt class=&quot;inline_code&quot;&gt;q()&lt;/tt&gt; function works the same as single-quoting your string, with the exception that you no longer need to escape single-quotes that appear within the string.  You would, however, have to escape any parentheses you need in the string.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;hr /&gt;&lt;/center&gt;&lt;h3&gt;qq&lt;/h3&gt;In the same way that double-quotes add interpolation to the functionality of single-quotes, doubling the &lt;tt class=&quot;inline_code&quot;&gt;q&lt;/tt&gt; adds interpolation to quoting without quotation marks.  For instance, if you wanted to avoid escape characters and interpolate &lt;tt class=&quot;inline_code&quot;&gt;$foo&lt;/tt&gt; in the above code, and wanted to use double-quotes around the word worth, you might do this:&lt;br /&gt;&lt;blockquote&gt;&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perl -wuse strict;my $foo;my $bar;$foo = 7;$bar = qq(it is &quot;worth&quot; $foo);print $bar;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;This example, when run, produces the following:&lt;br /&gt;&lt;blockquote&gt;&lt;tt class=&quot;inline_code&quot;&gt;it is &quot;worth&quot; 7&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;hr /&gt;&lt;/center&gt;&lt;h3&gt;qw&lt;/h3&gt;You can use qw to quote individual words without interpolation.  Use whitespace to separate terms you would otherwise have to separate by quoting individually and adding commas.  This is often quite useful when assigning lists to array variables.  The two following statements are equivalent:&lt;br /&gt;&lt;blockquote&gt;&lt;pre class=&quot;block_code&quot;&gt;@baz = (&#39;one&#39;, &#39;two&#39;, &#39;three&#39;);@baz = qw(one two three);&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;hr /&gt;&lt;/center&gt;&lt;h3&gt;here documents&lt;/h3&gt;If you want to quote many lines of text literally, you can use &quot;Here Document&quot; notation.  This consists of an introductory line which has two open angles (aka &quot;angle brackets&quot;: &lt;tt class=&quot;inline_code&quot;&gt;&lt;&lt;&lt;/tt&gt; ) followed by a keyword &amp;mdash; the end tag &amp;mdash; for signalling the end of the quote.  All text and lines following the introductory line are quoted. The quote ends when the end tag is found, by itself, on a line. For example, if the end tag is &lt;tt class=&quot;inline_code&quot;&gt;EOT&lt;/tt&gt;:&lt;br /&gt;&lt;blockquote&gt;&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perl -wuse strict;my $foo = 123.45;my $bar = &quot;Martha Stewedprune&quot;;print &lt;&lt;&quot;EOT&quot;;=====This is an example of   text taken literally   except that variables are   expanded where their   variable names appear.   foo: $foo   bar: $barEOT&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;This example, when run, produces the following:&lt;blockquote&gt;&lt;pre class=&quot;block_code&quot;&gt;=====This is an example of   text taken literally   except that variables are   expanded where their   variable names appear.   foo: 123.45   bar: Martha Stewedprune&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;The type of quotation marks placed around the end tag is important.  For instance, in the above example, &lt;tt class=&quot;inline_code&quot;&gt;EOT&lt;/tt&gt; is double-quoted, and as a result the values of &lt;tt class=&quot;inline_code&quot;&gt;$foo&lt;/tt&gt; and &lt;tt class=&quot;inline_code&quot;&gt;$bar&lt;/tt&gt; are substituted for the variable names.  Double-quoting the end tag causes the quoted block of text to be interpolated as it would be with double-quotes.  Use of single-quotes would cause it to be used literally, without interpolation, as though the quoted block of text were delimited by single-quotes rather than being referenced as a &quot;here document&quot;.  Omitting the quotation marks entirely defaults to behavior the same as using double-quotes.&lt;br /&gt;&lt;br /&gt;some notes to keep in mind:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The end tag specifier must follow the &lt;tt class=&quot;inline_code&quot;&gt;&lt;&lt;&lt;/tt&gt; without any intermediate space.&lt;/li&gt;&lt;li&gt;The actual end tag must be exactly the same as specified in the introduction line.&lt;/li&gt;&lt;li&gt;The introduction line must end with a semicolon.&lt;/li&gt;&lt;/ul&gt;The use of here documents is particularly useful in Perl scripts that include HTML and other markup, because it allows you to keep the markup relatively free of escape characters that would otherwise reduce the readability of it.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;hr /&gt;&lt;/center&gt;&lt;font size=&quot;-1&quot;&gt;Thanks due the PerlMonks community members who contributed suggestions and comments in discussion below.&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- Node text goes above. Div tags should contain sig only --&gt;&lt;div class=&quot;pmsig&quot;&gt;&lt;div class=&quot;pmsig-397229&quot;&gt;- &lt;font color=&quot;#0000ff&quot;&gt;a&lt;/font&gt;&lt;font color=&quot;#3355ff&quot;&gt;p&lt;/font&gt;&lt;font color=&quot;#6688ff&quot;&gt;o&lt;/font&gt;&lt;font color=&quot;#99bbff&quot;&gt;t&lt;/font&gt;&lt;font color=&quot;#99bbff&quot;&gt;h&lt;/font&gt;&lt;font color=&quot;#6688ff&quot;&gt;e&lt;/font&gt;&lt;font color=&quot;#3355ff&quot;&gt;o&lt;/font&gt;&lt;font color=&quot;#0000ff&quot;&gt;n&lt;/font&gt;&lt;br /&gt;&lt;a href=&quot;/out/http/?url=ccd.apotheon.org&quot;&gt;CopyWrite&lt;/a&gt; Chad Perrin&lt;/div&gt;&lt;/div&gt;
    </description>
</item>

        

<item>
    <title>Recursion: The Towers of Hanoi problem (DigitalKitty)</title>
    <link>http://prlmnks.org/html/400359.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/400359.html</guid>

    <description>
        Hi all.&lt;br /&gt;&lt;br /&gt;Many computer science professors eventually discuss the concept of recursion. To help illustrate the power and elegance (yes, there are drawbacks as well) it provides, a classic problem known as the &#39;Towers of Hanoi&#39; is often used.For those unfamiliar with this classic, please allow me explain the history and rules...&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The History:&lt;/h3&gt;&lt;br /&gt;The puzzle is called &quot;Towers of Hanoi&quot; because an early popular presentation wove a fanciful legend around it. According to this myth (uttered long before the Vietnam War), there is a Buddhist monastery at Hanoi which contains a large room with three time-worn posts in it surrounded by 21 golden discs. Monks, acting out the command of an ancient prophecy, have been moving these disks, in accordance with the rules of the puzzle, once every day since the monastery was founded over a thousand years ago. They are said to believe that when the last move of the puzzle is completed, the world will end in a clap of thunder. Fortunately, they are nowhere even close to being done.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Rules:&lt;/h3&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;There are n disks (1, 2, 3,..., n) and three towers (pegs). The towers are labeled &#39;A&#39;, &#39;B&#39;, and &#39;C&#39;.&lt;/li&gt;&lt;li&gt;All the disks are initially placed on the first peg (the &#39;A&#39; peg).&lt;/li&gt;&lt;li&gt;No disk may be placed on top of a smaller disk.&lt;/li&gt;&lt;li&gt;You may only move one disk at a time and this disk must be the top disk on a peg.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Code:&lt;/h3&gt;&lt;br &gt;&lt;pre class=&quot;block_code&quot;&gt;use warnings;use strict;# Towers of Hanoi# Perl version (5.8.0)# Ported from Javamy $numdisks = 0;print &quot;Number of disks? &quot;;chomp( $numdisks = &lt;STDIN&gt; );print &quot;The moves are:\n\n&quot;;movedisks( $numdisks, &#39;A&#39;, &#39;B&#39;, &#39;C&#39; );sub movedisks {  my( $num, $from, $to, $aux ) = @_;  if( $num == 1 ) {    print &quot;Move disk $num from $from to $to\n&quot;;  }  else {    movedisks( $num-1, $from, $aux, $to );    print &quot;Move disk $num from $from to $to\n&quot;;    movedisks( $num-1, $aux, $to, $from );  }}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Any suggestions on how to &#39;fine tune&#39; this program are more than welcome.&lt;br /&gt;&lt;br /&gt;Hope this proves interesting.&lt;br /&gt;&lt;br /&gt;Thanks,&lt;br /&gt;~Katie&lt;p&gt;&lt;small&gt;20041023 Edit by [Steve_p]: Changed title from &#39;Visiting the Towers of Hanoi.&#39;&lt;/small&gt;&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>Using the SNMP module from the Net-SNMP library (Rhys)</title>
    <link>http://prlmnks.org/html/396223.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/396223.html</guid>

    <description>
        &lt;h2&gt;Where to get Net-SNMP&lt;/h2&gt;You can get the Net-SNMP library package from &lt;a href=&quot;/out/http/?url=net-snmp.sourceforge.net%2F&quot;&gt;http://net-snmp.sourceforge.net/&lt;/a&gt;.  If you have RedHat Linux 9 or RedHat Enterprise Linux 3, you can install the net-snmp-5.0.9 packages from you installation CDs (or from RedHat Network, if you are fortunate enough to have access).&lt;p&gt;If you install from source, you will need to compile and install the libraries, then cd into the &#39;perl&#39; directory and install the Perl module separately.  If you install using RPMs from RedHat, you need the net-snmp-perl package and all of its dependencies.  If you build from the src.rpm package, make sure you use &lt;tt class=&quot;inline_code&quot;&gt;--with perl_modules&lt;/tt&gt;.&lt;p&gt;&lt;b&gt;NOTE:  If you use RPM, I highly recommend uninstalling the 5.0.9 packages provided by RedHat, getting the 5.1.x src.rpm, and rebuilding from there.&lt;/b&gt;  Version 5.1 resolves a problem that causes &#39;make test&#39; to fail any time you use MakeMaker.  Everything actually works, but you can&#39;t test anything.&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt;As of January, 2005, version 5.2.1 of Net-SNMP is available.  I have had no trouble with it so far.&lt;p&gt;&lt;h4&gt;Do Not Confuse Net-SNMP with Net::SNMP!&lt;/h4&gt;The naming is unfortunate, but the SNMP module that comes with the Net-SNMP package is just &#39;SNMP&#39;.  The Net::SNMP module is a completely different beast.  Confusing the two will get you in big trouble.  Here&#39;s the test:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;use SNMP;       # This is Net-SNMP.use Net::SNMP;  # This is NOT.  DO NOT USE WITH THIS TUTORIAL!&lt;/pre&gt;&lt;p&gt;Also, remember that the Net-SNMP package began life as UCD-SNMP, since it was originally sponsored and maintained by the University of California - Davis.  It was renamed in version 5.0 and has moved to SourceForge.  In fact, if you do &lt;tt class=&quot;inline_code&quot;&gt;install SNMP&lt;/tt&gt; from CPAN, you get the 4.2.0 module from the UCD-SNMP package.  It will &lt;i&gt;probably&lt;/i&gt; work with most of what you see here, but I recommend getting the 5.1 package if you can.&lt;hr /&gt;&lt;a name=&quot;TrivialQueries&quot;&gt;&lt;/a&gt;&lt;h2&gt;Try Some Trivial Queries&lt;/h2&gt;Before we get to the advanced stuff, let&#39;s make sure it&#39;s working.  You will need to have a device attached to the network that will respond to SNMP queries (you can use &#39;localhost&#39; if snmpd is running).  Edit the script below to suit your environment and try it.&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;#!/usr/bin/perluse warnings;use strict;use SNMP;use Socket;# VARIABLES YOU SHOULD EDIT.my $comm = &#39;public&#39;;    # EDIT ME!my $dest = &#39;localhost&#39;; # EDIT ME!my $mib  = &#39;sysDescr&#39;;  # Toy with this to get different                        # results.my $sver = &#39;2&#39;;         # EDIT ME!# VARIABLES YOU SHOULD LEAVE ALONE.my $sess; # The SNMP::Session object that does the work.my $var;  # Used to hold the individual responses.my $vb;   # The Varbind object used for the &#39;real&#39; query.# Initialize the MIB (else you can&#39;t do queries).&amp;SNMP::initMib();my %snmpparms;$snmpparms{Community} = $comm;$snmpparms{DestHost} = inet_ntoa(inet_aton($dest));$snmpparms{Version} = $sver;$snmpparms{UseSprintValue} = &#39;1&#39;;$sess = new SNMP::Session(%snmpparms);# Turn the MIB object into something we can actually use.$vb = new SNMP::Varbind([$mib,&#39;0&#39;]); # &#39;0&#39; is the instance.$var = $sess-&gt;get($vb); # Get exactly what we asked for.if ($sess-&gt;{ErrorNum}) {  die &quot;Got $sess-&gt;{ErrorStr} querying $dest for $mib.\n&quot;;  # Done as a block since you may not always want to die  # in here.  You could set up another query, just go on,  # or whatever...}print $vb-&gt;tag, &quot;.&quot;, $vb-&gt;iid, &quot; : $var\n&quot;;# Now let&#39;s show a MIB that might return multiple instances.$mib = &#39;ipNetToMediaPhysAddress&#39;; # The ARP table!$vb = new SNMP::Varbind([$mib]);  # No instance this time.# I prefer this loop method.  YMMV.for ( $var = $sess-&gt;getnext($vb);      ($vb-&gt;tag eq $mib) and not ($sess-&gt;{ErrorNum});      $var = $sess-&gt;getnext($vb)    ) {  print $vb-&gt;tag, &quot;.&quot;, $vb-&gt;iid, &quot; : &quot;, $var, &quot;\n&quot;;}if ($sess-&gt;{ErrorNum}) {  die &quot;Got $sess-&gt;{ErrorStr} querying $dest for $mib.\n&quot;;}exit;&lt;/pre&gt;&lt;p&gt;Whew!  That&#39;s a lot of code just for a couple of simple queries!  There are a lot of comments, and the code demonstrates the two most common ways of getting SNMP data from an agent (single query or loop through some unknown number of instances).  Your coding style may be more succint, and you may not need some of the error checking.  Proceed without it at your own peril, though.&lt;hr /&gt;&lt;h2&gt;And Now, A Few Words About MIBs&lt;/h2&gt;It might be worth defining a few terms before we go on:&lt;dl&gt;  &lt;dt&gt;&lt;b&gt;MIB&lt;/b&gt;&lt;/dt&gt; &lt;dd&gt;Strictly speaking, the Management Information Base or &quot;MIB&quot; is a database of information that you can query from an SNMP agent.  In practice, the term &#39;MIB&#39; by itself is confusing.  It is much better to be more specific and use one of the other terms here.&lt;br&gt;&lt;/dd&gt;  &lt;dt&gt;&lt;b&gt;MIB module&lt;/b&gt;&lt;/dt&gt; &lt;dd&gt;The actual specifications and definitions for a MIB, found in a file somewhere on your system.  It begins with &#39;YOUR-MIB-NAME DEFINITIONS ::= BEGIN&#39; and ends with &#39;END&#39;.  It is best to load MIB modules by name, since this allows Net-SNMP to do all of the file-searching for you, rather than hard-coding in file names.  This puts the onus on you to make sure there&#39;s only one file in your search path with definitions for a given MIB.&lt;/dd&gt;  &lt;dt&gt;&lt;b&gt;MIB file&lt;/b&gt;&lt;/dt&gt; &lt;dd&gt;A MIB file is just a text file that contains one or more MIB modules.  &lt;b&gt;NOTE:&lt;/b&gt; Net-SNMP has problems loading files with more than one MIB module in them.  In my experience, it only parses the first module properly.  This is a bug in Net-SNMP.  Please let me know if this has been solved so I can upgrade both my libraries and this file.&lt;/dd&gt;  &lt;dt&gt;&lt;b&gt;MIB object&lt;/b&gt;&lt;/dt&gt; &lt;dd&gt;A single item in a MIB specification such as &#39;sysDescr&#39;.  This is what people usually mean when they say they are &#39;looking for a MIB&#39; or have been &#39;querying a bunch of MIBs&#39;.  Each MIB object has a type (integer, string, enumerated, etc.).  MIB objects are queried by asking the agent to return one or more &lt;i&gt;instances&lt;/i&gt; of that object (more on this later).  Each instance of a MIB object has a value (which can be NULL).&lt;/dd&gt;  &lt;dt&gt;&lt;b&gt;MIB tree&lt;/b&gt;&lt;/dt&gt; &lt;dd&gt;Another, clearer term for describing the entire MIB.  The MIB itself is laid out in a tree structure, with MIB objects as the leaf nodes.  Each node is identified both by number (positive integers or zero) and by name (which is NOT guaranteed to be unique).  The tree layout is very flexible and provides an absolute unique path to every MIB object.  Each MIB module loaded adds new branches to the MIB tree and allows you to query the objects defined in the new module(s).&lt;/dd&gt;&lt;/dl&gt;&lt;p&gt;&lt;h3&gt;And Now, a Few Other Terms&lt;/h3&gt;I addressed &#39;MIBs&#39; first because there is so much confusion about that term.  There are also a few other things you&#39;ll need to recognize in order to use SNMP correctly:&lt;p&gt;&lt;ul&gt;  &lt;li&gt;&lt;b&gt;&#39;tag&#39;&lt;/b&gt; - In this context, this is the same as the MIB object name.  In your Varbinds, the tag value will get updated as part of a query, so keep an eye on it.  If you do a &lt;tt class=&quot;inline_code&quot;&gt;getnext&lt;/tt&gt;, you&#39;ll get an answer, even if the next object in the agent&#39;s MIB isn&#39;t in the same table.  You might &lt;i&gt;ask&lt;/i&gt; for the next physical in the ARP table and &lt;i&gt;get&lt;/i&gt; the first IP address in the table.  You&#39;ve jumped to the next MIB object.  Watch your tags.&lt;/li&gt;  &lt;li&gt;&lt;b&gt;&#39;oid&#39;&lt;/b&gt; - This is the Object ID.  A fully qualified OID is a long dotted-decimal string that shows how to get from the root of the MIB tree to the particular MIB object you&#39;re working with.  Example:  The OID for &#39;sysDescr&#39; is &#39;.1.3.6.1.2.1.1.1&#39;.  Note the leading dot.  Like in DNS, the optional leading dot makes the OID an absolute reference.  OIDs can also be relative.  Again, be careful.&lt;/li&gt;  &lt;li&gt;&lt;b&gt;&#39;iid&#39;&lt;/b&gt; - This is the Instance ID.  For some MIB objects, there is only one possible value, or &lt;i&gt;instance&lt;/i&gt;, like with &#39;sysLocation&#39;.  In those cases, the instance ID will be zero.  In other cases there can be a list of values, like the different network interfaces on a system (eth0, eth1, eth2), so the instance numbers will be positive integers, probably - but not &lt;i&gt;necessarily&lt;/i&gt; - incrementing in a simple way (e.g. &#39;1&#39;, &#39;2&#39;, &#39;3&#39;).  In still other cases, the SNMP agent may decide to keep some data in a more hash-like way, like in the ARP table (think &lt;tt class=&quot;inline_code&quot;&gt;$ARP{&#39;ip&#39;} = $mac;&lt;/tt&gt;).  In that case, the instance ID will be complicated, like &#39;0.10.4.15.2.45&#39;.  In &lt;i&gt;every&lt;/i&gt; case, the Instance ID is the sub-identifier that gets tacked onto the end of the OID to specify that particular value.  Here are some examples:&lt;p&gt;  &lt;ol&gt;    &lt;li&gt;&lt;b&gt;sysDescr.0&lt;/b&gt; - Only one instance, so the IID is zero.&lt;/li&gt;    &lt;li&gt;&lt;b&gt;ifIndex.1&lt;/b&gt; - Probably a simple list, so the IIDs start with one and increment.&lt;/li&gt;    &lt;li&gt;&lt;b&gt;ipNetToMediaPhysAddress.2050.10.1.1.50&lt;/b&gt; - This is the hash-like IID.  In this case, &#39;10.1.1.50&#39; was the IP address learned on the interface whose ifIndex is &#39;2050&#39;.  The &lt;i&gt;value&lt;/i&gt; of this object is something like &#39;00:08:ad:44:13:62&#39;.  So the IID is &#39;2050.10.1.1.50&#39; which is like a &#39;key&#39; in the &#39;hash&#39; for &#39;ipNetToMediaPhysAddress&#39;.&lt;p&gt;Your mileage &lt;i&gt;will&lt;/i&gt; vary both among different MIB objects and different agents you query.  I have seen different routers respond at least three different ways to queries for the same MIB object.  (Each router answers the same all the time, but the different routers&#39; answers differ from &lt;i&gt;each other&lt;/i&gt;.)  In theory, this &lt;i&gt;shouldn&#39;t&lt;/i&gt; happen, since the same MIB object should be defined the same way in every case, so the routers should all respond in the same way.  I have learned to be paranoid about this anyway, and make no assumptions about the returned data.&lt;/li&gt;  &lt;/ol&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h2&gt;And Now, We&#39;ll Add Enterprise MIB Files&lt;/h2&gt;Net-SNMP comes with plenty of RFC-defined MIB modules, usually stored in /usr/share/snmp/mibs.  However, most of the really good info you want from an SNMP agent is stored in the proprietary &lt;b&gt;Enterprise MIBs&lt;/b&gt; (dum dum DUM!).  These MIBs are stored in the &#39;enterprises&#39; MIB subtree.  Each vendor has its own identifier (e.g. &#39;cisco&#39;, &#39;nortel&#39;, &#39;rapidCity&#39;), and under that, the vendor is free to create all the subtrees and objects they want.  But for &lt;i&gt;you&lt;/i&gt; to be able to get to them, you need to get Net-SNMP to parse the definitions for all this great stuff.  You need to get it to load the MIB modules for your enterprise MIBs.&lt;p&gt;This is really a two-part problem.  First, where are you going to keep the MIB files themselves?  Second, how are you going to get the files imported when you go to do SNMP queries?  I&#39;ll tell you how I did it, and hopefully you&#39;ll e-mail me if you find some horrible deficiency in this method.&lt;h3&gt;Look, I Just Want to Load One File!&lt;/h3&gt;Fine.  Here&#39;s the fastest - and most unwise - way to do it.  It works, of course, but you&#39;ll soon find that this method is rife with practical problems:&lt;pre class=&quot;block_code&quot;&gt;&amp;SNMP::addMibFiles(&quot;/path/to/some/file.mib&quot;);&amp;SNMP::initMib();&lt;/pre&gt;&lt;h3&gt;So What&#39;s So Bad About That?&lt;/h3&gt;Since you asked, I&#39;ll tell you.&lt;p&gt;First, that&#39;s a hard-coded path to a particular file.  The path may change.  The file name may change, which happens a lot when vendors mark the version of a MIB module in the file name.  This method is extremely resistant to change.&lt;p&gt;Second, what if this MIB module requires that you load another module first?  Done this way, you&#39;ll probably have to load all of the pre-requisite files &lt;i&gt;by hand&lt;/i&gt; before this one will work, especially if the prereqs are other enterprise MIB modules.  There&#39;s a better way.  Let&#39;s go back to the beginning and pretend we want to do things the Right Way(tm).&lt;h3&gt;Where to Put the Files&lt;/h3&gt;If you installed from RPM, the MIB files the come with Net-SNMP are put in /usr/share/snmp/mibs (or /usr/local/share/snmp/mibs if you installed from source).  Every time I added a group of related MIBs files, I put them in a subdirectory under this one.  For example, I wrote a program called JScan, and put several subdirectories named JScan/APC, JScan/BayStack, etc. for a full path of /usr/share/snmp/mibs/JScan/APC.  This kept all of the files separate (so &#39;rm -r ..../JScan&#39; would get rid of them all in a pinch), but in a predictable and sensible place.&lt;p&gt;Then a second problem presented itself.  I decided it was a pain to add that many search directories all of the time (discussed below), so I created a single directory /usr/share/snmp/mibs/JScan/everything that contains symbolic links to all of the actual files in all of the other directories.  This is done at install time by this excerpt of the post-install script:&lt;pre class=&quot;block_code&quot;&gt;# Where $destdir is /usr/share/snmp/mibs in most cases...system   &quot;mkdir -p $destdir/JScan/everything ;   cd $destdir/JScan/everything ;   find .. -type f -exec ln -sf {} \\;&quot;;&lt;/pre&gt;&lt;p&gt;I then installed the MIB files for other packages in other subdirs under /usr/share/snmp/mibs.  Again, keeps things separate, but still in more or less the Right Place.&lt;p&gt;&lt;b&gt;Known Problem:&lt;/b&gt;  While this has not happened to me yet in practice, it is &lt;i&gt;possible&lt;/i&gt; that two vendors may name their MIB files with the same name, in which case &#39;ln&#39; above will return an error when it tries to create the second link.  This has never happened to me yet, though I have the practice of pulling the RFC-based MIB files out of the vendor-supplied list before I split them up, which resolves a LOT of conflicts.&lt;p&gt;&lt;h3&gt;Get Perl to Read Your MIB Files&lt;/h3&gt;There are several ways to do this, but in my opinion the &lt;i&gt;best&lt;/i&gt; way is as follows.  Suppose I wanted to load the MIB modules &#39;S5-CHASSIS-MIB&#39;, &#39;RAPID-CITY&#39;, &lt;i&gt;and&lt;/i&gt; all of their pre-requisites.  I would do this:&lt;pre class=&quot;block_code&quot;&gt;# Add the search directory.&amp;SNMP::addMibDirs(&quot;/usr/share/snmp/mibs/JScan/everything&quot;);# Load the modules AND their pre-reqs.&amp;SNMP::loadModules(&#39;S5-CHASSIS-MIB&#39;, &#39;RAPID-CITY&#39;);# Wonder-Twin powers, ACTIVATE!&amp;SNMP::initMib();&lt;/pre&gt;In the example shown, the directories /usr/share/snmp/mibs AND /usr/share/snmp/mibs/JScan/everything will be searched for a file with the S5-CHASSIS-MIB module.  It will then load that file.  Since the S5-CHASSIS-MIB also requires the S5-ROOT-MIB, those same directories will be searched again for the file containing THAT MIB module, and so on until all the necessary modules have been loaded, or until something fails.  If I load a non-existent module THIS-AND-THAT on my system, I get:&lt;pre class=&quot;block_code&quot;&gt;Cannot find module (THIS-AND-THAT): At line 1 in (none)&lt;/pre&gt;You can, of course, turn this off and make it fail silently, but by default it won&#39;t cause your script to fail.  The MIB parsing errors can be turned on or off in your snmp.conf file.&lt;h3&gt;Other Useful Bits&lt;/h3&gt;There are several other ways you can get Net-SNMP to add directories to your search path and/or automatically load MIB modules.  See the &lt;tt class=&quot;inline_code&quot;&gt;snmp.conf(5)&lt;/tt&gt; man page for more details, paying particular attention to the parts about the &lt;tt class=&quot;inline_code&quot;&gt;MIBS&lt;/tt&gt; and &lt;tt class=&quot;inline_code&quot;&gt;MIBDIRS&lt;/tt&gt; environment variables and the &lt;tt class=&quot;inline_code&quot;&gt;~/.snmp/snmp.conf&lt;/tt&gt; file, which might be more appropriate than making system-wide changes.&lt;p&gt;&lt;h2&gt;Review&lt;/h2&gt;At this time, I would like to suggest that you go back to &lt;a href=&quot;#TrivialQueries&quot;&gt;Try Some Trivial Queries&lt;/a&gt; and play for a bit.  Re-write this code in your own style, taking the time to understand as much of it as possible.  Try loading some MIB modules and querying new stuff from those modules.  Get used to OIDs, IIDs, values, and MIB object definitions before you proceed to the next section, in which we start doing the dangerous stuff (changing things on a remote agent).&lt;hr /&gt;&lt;h2&gt;Setting MIB Object Values&lt;/h2&gt;Okay, so we&#39;ve covered how to get Net-SNMP, load new MIB modules, and query some MIB objects.  Suppose now that you want to use Net-SNMP to set the value of a read/write MIB object, such as sysName or sysLocation.  This is actually pretty simple... most of the time.  Take these two objects for instance.  Here&#39;s the code to set the value of sysName on a host:&lt;pre class=&quot;block_code&quot;&gt;my $comm = &#39;ihavepower&#39;; # Use read/write community.my $dest = &#39;10.1.1.1&#39;;  # IP or DNS will work.my $sver = &#39;2&#39;;  # Use 1 for simple devices, and 3 if you                 # really know your SNMP security.my %snmpparms;$snmpparms{Community} = $comm;$snmpparms{DestHost} = inet_ntoa(inet_aton($dest));$snmpparms{Version} = $sver;$snmpparms{UseSprintValue} = 1;my $sess = new SNMP::Session(%snmpparms);my $mib = &#39;sysName&#39;;my $instance = &#39;0&#39;; # There&#39;s only one instance of sysName.my $value = &quot;New system name.&quot;;my $vb = new SNMP::Varbind([$mib,$instance,$value]);# This does it!$sess-&gt;set($vb);if ( $sess-&gt;{ErrorNum} ) {  print &quot;Got $sess-&gt;{ErrorStr} setting $mib on $host.\n&quot;;}&lt;/pre&gt;This works for most things.  However, I have run into a lot of trouble when trying to set values that aren&#39;t strings or integers when I have set UseSprintValue to true, which I usually do, since subsequent queries using the same session make FAR more sense with UseSprintValue (which translates enums and some packed binary values into readable strings for the user).  Setting packed binary values, in particular, is a pain.  Fortunately, all you need is a second session to cure this:&lt;pre class=&quot;block_code&quot;&gt;my $comm = &#39;ihavepower&#39;; # Use read/write community.my $dest = &#39;10.1.1.1&#39;;  # IP or DNS will work.my $sver = &#39;2&#39;;  # Use 1 for simple devices, and 3 if you                 # really know your SNMP security.my %snmpparms;$snmpparms{Community} = $comm;$snmpparms{DestHost} = inet_ntoa(inet_aton($dest));$snmpparms{Version} = $sver;$snmpparms{UseSprintValue} = 0;### NEW SESSION REQUIRED!my $sess2 = new SNMP::Session(%snmpparms);my $mib = &#39;some32BitMib&#39;;  # Suppose it takes a packed IP.my $instance = &#39;0&#39;;        # Will vary with the MIB object.my $value = inet_aton($ipaddr);my $vb = new SNMP::Varbind([$mib,$instance,$value]);$sess2-&gt;set($vb);if ( $sess2-&gt;{ErrorNum} ) {  print &quot;Got $sess2-&gt;{ErrorStr} setting $mib on $host.\n&quot;;}&lt;/pre&gt;Note that it&#39;s almost entirely the same except that UseSprintValue is set to zero when the SNMP session object is created.&lt;hr /&gt;&lt;h2&gt;Using VarLists&lt;/h2&gt;Sometimes you want to query a bunch of different SNMP values on the same device.  You could query each of them one at a time, but if you want to conserve bandwidth or if you&#39;re trying to keep several variables in sync it&#39;s a lot easier to use a VarList.&lt;p&gt;So what&#39;s a VarList?  A VarList is a blessed reference to an array of Varbinds (so you can&#39;t just do &lt;tt class=&quot;inline_code&quot;&gt;push @varbinds, $vb;&lt;/tt&gt; in a loop and expect that to work).  So basically, a VarList is a bunch of Varbinds stuck together so you can make many queries at once.  Let&#39;s walk through two examples of using VarLists and see how they work.&lt;p&gt;Here we create a VarList and query a device for the variables &#39;sysName&#39;, &#39;sysDescr&#39;, and &#39;sysLocation&#39;.  We&#39;re assuming that the session is already created and we&#39;re going to just query instance 0, since we know from experience that this is the only instance that exists for these MIB objects.&lt;pre class=&quot;block_code&quot;&gt;$MIB[0] = &#39;sysName&#39;;$MIB[1] = &#39;sysDescr&#39;;$MIB[2] = &#39;sysLocation&#39;;$vl = new SNMP::VarList([$MIB[0], 0],                        [$MIB[1], 0],                        [$MIB[2], 0]);@ANSWERS = $sess-&gt;get($vl);&lt;/pre&gt;&lt;p&gt;And that&#39;s it!  Instead of using one array constructor with &quot;MIB, instance, value&quot; inside of it like with a Varbind, you just create a list of them.  Now let&#39;s do that same query above, but this time we&#39;ll use a loop to create an array of Varbinds.  For this example, it&#39;s trivial, but this can make for an elegant solution in some cases and save you a lot of code and a lot of bandwidth.&lt;pre class=&quot;block_code&quot;&gt;@MIBS = (&#39;sysName&#39;, &#39;sysDescr&#39;, &#39;sysLocation&#39;);foreach $mib ( @MIBS ) {  push @bunchovbs, new SNMP::Varbind([$mib,0]);}# Now the magic!$vl = new SNMP::VarList(@bunchovbs);@ANSWERS = $sess-&gt;get($vl);&lt;/pre&gt;This method is most useful when the instance number or the value you need in the Varbind is only known after some calculation AND you want to put several MIB objects in the same &lt;tt class=&quot;inline_code&quot;&gt;get&lt;/tt&gt; or &lt;tt class=&quot;inline_code&quot;&gt;set&lt;/tt&gt; action.  Here&#39;s a more useful example of using a VarList:&lt;pre class=&quot;block_code&quot;&gt;@MIBS = (&#39;ifAdminStatus&#39;, &#39;ifOperStatus&#39;, &#39;ifSpeed&#39;);$vl = new SNMP::VarList([$MIBS[0]], [$MIBS[1]], [$MIBS[2]]);for ( $ifindex = 1 ; $ifindex &lt; 25 ; $ifindex++ ) {  @STATUS = $sess-&gt;getnext($vl);  if ( $STATUS[0] eq &#39;up&#39; ) { print &quot;Port $ifindex enabled.\n&quot;; }  else next;  print &quot;  Link status is $STATUS[1].  Speed is $STATUS[2].\n&quot;;}&lt;/pre&gt;Now we skipped all the setup and there&#39;s absolutely no error checking in the loop shown, but you can see how using VarLists can drastically shorten the process of getting (or setting) several MIB objects at once.&lt;p&gt;&lt;b&gt;TIP:&lt;/b&gt; One problem I&#39;ve come across when using VarLists in this way is that in some cases the &lt;tt class=&quot;inline_code&quot;&gt;getnext&lt;/tt&gt; causes one of the MIB objects in the list to get a different instance number than the others.  Suppose in the example above that the switch does not keep a value for &#39;ifOperStatus&#39; at all if &#39;ifAdminStatus&#39; is &#39;down&#39;.  If port 2 is disabled, then on the second query, the instance ID for &lt;tt class=&quot;inline_code&quot;&gt;$$vl[0]&lt;/tt&gt; will be 2, but for the other two objects the instance will be &lt;b&gt;3&lt;/b&gt; (assuming port 3 is enabled).  The &lt;tt class=&quot;inline_code&quot;&gt;getnext&lt;/tt&gt; is performed on all of the MIBs &lt;i&gt;regardless of the success or failure or values of the other MIBs in the same query&lt;/i&gt;  SNMP doesn&#39;t magically &#39;know&#39; you want the objects in your VarList to be in sync.&lt;p&gt;&lt;b&gt;SO:&lt;/b&gt;  When using VarLists, even though you&#39;re querying them all at once and they share a packet, they are &lt;i&gt;separate&lt;/i&gt; queries, so if you want them to stay in sync, you may need to add code to make sure they actually do.  Check that all of the instance IDs are the same after each query and then do whatever is appropriate to resolve it when they turn up unequal.  Sometimes a &lt;tt class=&quot;inline_code&quot;&gt;getnext&lt;/tt&gt; will skip an instance, but going back and doing a &lt;tt class=&quot;inline_code&quot;&gt;get&lt;/tt&gt; on that same instance will return the information you want.&lt;hr /&gt;&lt;h2&gt;Getting Many Values in ONE Query&lt;/h2&gt;So far, we have been using SNMP commands that were defined in version 1 of the SNMP specification:  GET, GETNEXT, and SET.  In version 2, the SNMP designers decided that they wanted a way to send a single query that would return N values of a single object, like doing 20 &quot;GETNEXTs&quot; at once.  To do this, they created the GETBULK command.&lt;p&gt;The syntax for the &lt;tt class=&quot;inline_code&quot;&gt;getbulk&lt;/tt&gt; method in the SNMP module is a little complicated.  Here&#39;s what &lt;tt class=&quot;inline_code&quot;&gt;perldoc&lt;/tt&gt; has to say about it:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;$sess-&gt;getbulk(&lt;non-repeaters&gt;, &lt;max-repeaters&gt;, &lt;vars&gt;)  do an SNMP GETBULK, from the list of Varbinds, the single next lex-  ico instance is fetched for the first n Varbinds as defined by  &lt;non-repeaters&gt;. For remaining Varbinds, the m lexico instances are  retrieved each of the remaining Varbinds, where m is  &lt;max-repeaters&gt;.&lt;/pre&gt;&lt;p&gt;So the first two arguments, &lt;tt class=&quot;inline_code&quot;&gt;non-repeaters&lt;/tt&gt; and &lt;tt class=&quot;inline_code&quot;&gt;max-repeaters&lt;/tt&gt; are integers that define how &lt;tt class=&quot;inline_code&quot;&gt;getbulk&lt;/tt&gt; is going to behave, and the remaining arguments are Varbinds (or better, a VarList).&lt;p&gt;Now &lt;tt class=&quot;inline_code&quot;&gt;getbulk&lt;/tt&gt; is a little tricky.  It&#39;s behaves like a bunch of &lt;tt class=&quot;inline_code&quot;&gt;getnext&lt;/tt&gt; commands strung together.  If &lt;tt class=&quot;inline_code&quot;&gt;non-repeaters&lt;/tt&gt; is set to &#39;4&#39;, it will take the first four Varbinds in the list given and get their &lt;i&gt;next&lt;/i&gt; values exactly once (as if you had used &lt;tt class=&quot;inline_code&quot;&gt;getnext&lt;/tt&gt; on each of them).  Then if we suppose that &lt;tt class=&quot;inline_code&quot;&gt;max-repeaters&lt;/tt&gt; is set to &#39;10&#39;, &lt;tt class=&quot;inline_code&quot;&gt;getbulk&lt;/tt&gt; will behave like a &lt;tt class=&quot;inline_code&quot;&gt;getnext&lt;/tt&gt; on the remaining Varbinds 10 times &lt;i&gt;as a list&lt;/i&gt;.  So it doesn&#39;t get the next 10 of the first Varbind, then get 10 of the next Varbind, and so on, but rather it does 10 &lt;tt class=&quot;inline_code&quot;&gt;getnext&lt;/tt&gt;&#39;s &lt;i&gt;on the list&lt;/i&gt; (just as if you had used a &lt;tt class=&quot;inline_code&quot;&gt;for&lt;/tt&gt; loop on a VarList).&lt;p&gt;So let&#39;s take an example that I threw together that queries some basic stuff about a 24-port switch, and hopefully things will become clearer:&lt;p&gt;&lt;pre class=&quot;block_code&quot;&gt;use SNMP;use Socket;# Set up the SNMP session.my %snmpparms = ();$snmpparms{DestHost} = inet_ntoa(inet_aton($host));$snmpparms{Community} = &#39;public&#39;;$snmpparms{UseSprintValue} = &#39;1&#39;;  # readable!$snmpparms{Version} = &#39;2&#39;;  # MUST USE 2 for GETBULK!my $sess = new SNMP::Session(%snmpparms);# I prefer to use VarLists for this sort of thing, since# we have enough confusion without making the actual# getbulk() call complicated.my @vbs = ();foreach my $mib (  &#39;sysName&#39;,  &#39;sysDescr&#39;,  &#39;sysLocation&#39;,  &#39;sysUpTime&#39;,  &#39;ifIndex&#39;,  &#39;ifAdminStatus&#39;,  &#39;ifOperStatus&#39;  ) {  push @vbs, new SNMP::Varbind([$mib]);}my $vl = new SNMP::VarList(@vbs);# We&#39;ll keep our answers in these.my %sysStuff;my @ANSWERS;# Query the first four objects ONCE EACH, and store the# answers in the appropriate places in %sysStuff.# Then get ifIndex and ifAdminStatus 24 times and store# all of those reponses in @ANSWERS.($sysStuff{Name}, $sysStuff{Descr}, $sysStuff{Location}, $sysStuff{UpTime}, @ANSWERS) = $sess-&gt;getbulk(4, 24, $vl);  # AT LAST!# Always, always, always...if ( $sess-&gt;{ErrorNum} ) {  die &quot;Got &quot;, $sess-&gt;{ErrStr}, &quot; during getbulk.\n&quot;;}# So $ANSWERS[0] now contains the first value of ifIndex.# $ANSWERS[1] contains the FIRST VALUE OF ifAdminStatus,# NOT the second value of ifIndex.# The remaining code could be MUCH simpler, but it&#39;s done# this way to illustrate how the answers are returned.my @INDEXES;my @STATUS;for ( my $x = 0 ; @ANSWERS ; $x++ ) {  # Smart people would probably use map() for this.  # I&#39;m not that smart...  $INDEXES[@INDEXES] = shift @ANSWERS;  $STATUS[@STATUS] = shift @ANSWERS;  # So we round-robin between @INDEXES and @STATUS,  # thus &quot;unstriping&quot; the responses stored in @ANSWERS.}print &quot;Name:         $sysStuff{Name}\n&quot;;print &quot;Description:  $sysStuff{Descr}\n&quot;;print &quot;Location:     $sysStuff{Location}\n&quot;;print &quot;Uptime:       $sysStuff{UpTime}\n&quot;;print &quot;\n&quot;;# This now prints out clearly.for ( my $x = 0 ; $x &lt;= $#INDEXES ; $x++ ) {  print &quot;  INDEX: $INDEXES[$x]  STATUS:  $STATUS[$x]\n&quot;;}&lt;/pre&gt;&lt;p&gt;So we asked for four non-repeaters, sysName, sysDescr, sysLocation, and sysUpTime.  We also ask for 24 instances of ifIndex and ifAdminStatus.  The first four objects are queried once each, then the 24 answers for ifIndex and ifAdminStatus are &quot;striped&quot; together, and we use a simple &lt;tt class=&quot;inline_code&quot;&gt;for&lt;/tt&gt; loop to break them apart again.&lt;p&gt;Now, if this were a real program, we would have just used @ANSWERS directly in the output&lt;tt class=&quot;inline_code&quot;&gt;for&lt;/tt&gt; loop at the bottom and done &lt;tt class=&quot;inline_code&quot;&gt;$x+=2&lt;/tt&gt; for each iteration and saved a lot of code and extra variables, but I digress...&lt;p&gt;Using the &lt;tt class=&quot;inline_code&quot;&gt;getbulk&lt;/tt&gt; command with &lt;tt class=&quot;inline_code&quot;&gt;max-repeaters&lt;/tt&gt; set to less than &#39;2&#39; is silly, though it can be used with &lt;tt class=&quot;inline_code&quot;&gt;non-repeaters&lt;/tt&gt; set to &#39;0&#39;.  There is no requirement to have any non-repeaters in your query.&lt;p&gt;&lt;b&gt;WARNING:&lt;/b&gt;  The &lt;tt class=&quot;inline_code&quot;&gt;getbulk&lt;/tt&gt; command is not the Hold Grail of Supah-Queries.  You can&#39;t just ask it to return 1000 instances, because SNMP &lt;i&gt;will only send one packet in reply&lt;/i&gt;.  SNMP can&#39;t fragment its responses into multiple UDP messages, and &lt;i&gt;won&#39;t&lt;/i&gt; send a single UDP message that would cause the IP packet to be fragmented either, so you&#39;ll have to use &lt;tt class=&quot;inline_code&quot;&gt;getbulk&lt;/tt&gt; with a  little circumspection.  I&#39;ve found that I can safely pack about 75 small queries (for &#39;ifAdminStatus&#39;, say) into a single &lt;tt class=&quot;inline_code&quot;&gt;getbulk&lt;/tt&gt;, but that&#39;s about it.  &lt;b&gt;CHECK YOUR RESPONSES!&lt;/b&gt;&lt;p&gt;&lt;b&gt;NOTE:&lt;/b&gt;  It should be noted that I haven&#39;t tried to see if this limitation still exists in SNMP version 3 when using TCP instead of UDP.  If anyone gets large queries to work using this - or any other - method, &lt;b&gt;&lt;i&gt;PLEASE&lt;/i&gt;&lt;/b&gt; let me know.  You can imagine how much simpler it would make large queries.&lt;hr /&gt;&lt;h2&gt;Planned:&lt;/h2&gt;&lt;ol&gt;  &lt;li&gt;Using the callback (SNMP in the background!)&lt;/li&gt;  &lt;li&gt;Using SNMPv3 (NO MORE CLEARTEXT &#39;PASSWORDS&#39;!)&lt;/li&gt;&lt;/ol&gt;&lt;h2&gt;Quick and Dirty Synopses of Planned Stuff for the Impatient&lt;/h2&gt;Heh.  This is also to help motivate me to get this writeup finished.  Perhaps it will help you make sense of the documentation you hopefully referred to already.&lt;ol&gt;  &lt;li&gt;&lt;b&gt;Using the callback&lt;/b&gt; - The short version of this is you pass &lt;tt class=&quot;inline_code&quot;&gt;get()&lt;/tt&gt;, &lt;tt class=&quot;inline_code&quot;&gt;getnext()&lt;/tt&gt;, or &lt;tt class=&quot;inline_code&quot;&gt;getbulk()&lt;/tt&gt; a reference to a subroutine that should be executed when the response arrives (works with the SET commands as well).  Then you run a waiting function to sit and allow them all to be processed.  Can &lt;i&gt;seriously&lt;/i&gt; speed up things like querying many different devices.&lt;/li&gt;  &lt;li&gt;&lt;b&gt;SNMPv3&lt;/b&gt; - User names, passwords, authentication, and privacy.  Using the authentication feature means you may or may not have to supply a user name and password (as opposed to a plain ol&#39; community) when you query the device.  Using the privacy feature means you can set up an encrypted session (typically TLS) for your queries, so people can&#39;t see your user/pass or communities or the data you asked for, any of which could be considered sensitive data.&lt;/li&gt;&lt;/ol&gt;Sorry I don&#39;t have time (well, patience) to write more on these topics at the moment.  I promise to get back to it, though.  They say the best way to learn is to teach.  Well, I&#39;ve learned a bit myself while writing this.  Suggestions on re-organizing and/or reformatting this document are welcomed.  Flames and pointless criticisms can be sent to 127.0.0.1:25.
    </description>
</item>

        

<item>
    <title>Including files (Juerd)</title>
    <link>http://prlmnks.org/html/393426.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/393426.html</guid>

    <description>
        &lt;h2&gt;No include&lt;/h2&gt;&lt;p&gt;Some simple languages, like PHP, offer an &lt;tt&gt;include()&lt;/tt&gt; to include a file literally. Perl does not. Then how can you still load code from other files?&lt;/p&gt;&lt;p&gt;There are many ways to do this in Perl, but there is no easy way to get close to what most people expect of an &lt;tt&gt;include()&lt;/tt&gt;. People who want to include files usually come from simpler languages, or have no programming experience at all. The hardest thing they will have to learn is that &lt;b&gt;you should not want to include a file&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;That may sound harsh, but it&#39;s a Perl reality. In Perl, we don&#39;t include or link libraries and code reuse isn&#39;t usually done by copying and pasting. Instead, Perl programmers use &lt;b&gt;modules&lt;/b&gt;. The keywords [use] and [require] are meant for use with modules. Only in the simplest of situations you can get away with abusing [require] as if it were some kind of &lt;tt&gt;include()&lt;/tt&gt;, but it&#39;s easy to get bitten by how it works: it only loads any given file &lt;b&gt;once&lt;/b&gt;.&lt;/p&gt;&lt;h2&gt;Creating a module&lt;/h2&gt;&lt;p&gt;What is a module, anyway? [perlmod] defines it as: &lt;em&gt;just a set of related functions in a library file, i.e., a Perl package with the same name as the file.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Creating a module is EASY, but it is a little more work than just creating a file with code in it. First, you need to think of a module name. This is the basis for both the filename and the package name, and these have to be synchronised for some features to work. For project specific modules, I always create a new top-level namespace with the name of the project. For example, &lt;tt&gt;NameOfTheProject/SomeModule.pm&lt;/tt&gt; is a good filename (in real life, use something a little more meaningful). The corresponding package is &lt;tt&gt;NameOfTheProject::SomeModule&lt;/tt&gt;. Use CamelCaps like this, because everyone else does too.&lt;/p&gt;&lt;p&gt;The file must be in a directory that is listed in &lt;tt&gt;@INC&lt;/tt&gt;. To find out what your &lt;tt&gt;@INC&lt;/tt&gt; is, run &lt;tt&gt;perl -V&lt;/tt&gt;. The current working directory (listed as its symbolic name &lt;tt&gt;.&lt;/tt&gt; (a single dot)) should be listed. To begin with, putting the module in the script&#39;s directory is a good idea. It is the easiest way to keep things organized. If you want to put the module somewhere else, you will have to update &lt;tt&gt;@INC&lt;/tt&gt;, so that perl knows where to find it. An easy way to do get code like this in the main script:&lt;pre class=&quot;block_code&quot;&gt;use lib &#39;path/to/the/modules&#39;;# The example module could be path/to/the/modules/NameOfTheProject/SomeModule.pm&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;What goes in the module itself doesn&#39;t require much explanation. I&#39;ll just give a complete example of a simple NameOfTheProject::SomeModule:&lt;pre class=&quot;block_code&quot;&gt;use strict;package NameOfTheProject::SomeModule;sub some_function {    # put sane code here    return 123;}1;&lt;/pre&gt;Just list all the subs as you usually would, put a [package] statement at the top and a true value at the bottom (&lt;tt&gt;1&lt;/tt&gt; will suffice). Obviously, [use] [strict] is a good idea. You should never code a module that does not have this. Beware: A &lt;tt&gt;use strict;&lt;/tt&gt; statement in the main script has no effect on the module.&lt;/p&gt;&lt;p&gt;A module runs only once. That means that for code to be reusable, it &lt;b&gt;must&lt;/b&gt; be in a sub. In fact, it&#39;s considered very bad style to do anything (except declaring and initializing some variables) in the module&#39;s main code. Just don&#39;t do that.&lt;/p&gt;&lt;p&gt;You can now load the module and use its sub, simply by doing:&lt;pre class=&quot;block_code&quot;&gt;use NameOfTheProject::SomeModule;print NameOfTheProject::SomeModule::some_function();  # prints 123&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;You can have the module export its sub(s) to the caller&#39;s namespace (that is: the package the [use] statement is in. By default, this is &lt;tt&gt;main&lt;/tt&gt;). For this, put after the [package] statement:&lt;pre class=&quot;block_code&quot;&gt;use base &#39;Exporter&#39;;our @EXPORT_OK = (&#39;some_function&#39;);&lt;/pre&gt;Then, when [use]ing the module, you can request that &lt;tt&gt;some_function&lt;/tt&gt; be imported to your namespace with:&lt;pre class=&quot;block_code&quot;&gt;use NameOfTheProject::SomeModule (&#39;some_function&#39;);print some_function();  # prints 123&lt;/pre&gt;To have it exported automatically, use &lt;tt&gt;@EXPORT&lt;/tt&gt; instead of &lt;tt&gt;@EXPORT_OK&lt;/tt&gt;. This will eventually bite you if the function names are generic. For example, many people get bitten by [cpan://LWP::Simple]&#39;s &lt;tt&gt;get&lt;/tt&gt; function. It is not unlikely that you already have one.&lt;/p&gt;&lt;p&gt;There are more ways to export functions. I of course prefer to use my own module [cpan://Exporter::Tidy]. Not only because it&#39;s smaller and often faster, but mostly because it lets the user of a module define a prefix to avoid clashes. Read its documentation for instructions.&lt;/p&gt;&lt;p&gt;For the export/import mechanism, it is very important that the filename, the package name and the name used with [use] are equal. This is case sensitive. (Ever wondered why under Windows, &lt;tt&gt;use Strict;&lt;/tt&gt; doesn&#39;t enable [strict], but also doesn&#39;t emit any warning or error message? It has everything to do with the case insensitive filesystem that Windows uses.)&lt;/p&gt;&lt;h2&gt;Stubbornly still wanting to include&lt;/h2&gt;&lt;p&gt;Sometimes, a module just isn&#39;t logical. For example, when you want to use an external configuration file. (Many beginners and people who post code online put configuration in the script itself for ease of use, but this makes upgrading the script harder.) There are many configuration file reader modules you can use, but why use one of those if you can just use bare Perl?&lt;/p&gt;&lt;p&gt;This is where [do] comes in. What [do] does is very close to what an [include] would do, but with a very annoying exception: the new file gets its own lexical scope. In other words: a variable declared with [my] is not accessible externally. This follows all logical rules attached to lexical variables, but can be very annoying. Fortunately, this does not have to be a problem. [do] returns whatever the included script returned, and if you make that script just the contents of a hash, here&#39;s my favourite way to offer configurability:&lt;pre class=&quot;block_code&quot;&gt;# This is config.plmirror     =&gt; &#39;http://www.nl.example.com/mirror&#39;,path       =&gt; &#39;/var/www/example&#39;,skip_files =&gt; [ &#39;png&#39;, &#39;gif&#39;, &#39;jpg&#39; ],&lt;/pre&gt;(The last &lt;tt class=&quot;inline_code&quot;&gt;,&lt;/tt&gt; is optional, but it&#39;s included to make adding a line easier.)&lt;pre class=&quot;block_code&quot;&gt;# This is script.pluse strict;my %config = do &#39;config.pl&#39;;chdir $config{path};...&lt;/pre&gt;Error checking is left as an excercise.&lt;/p&gt;&lt;p&gt;Because we used only the return value of the script, and never even touched a variable in &lt;tt&gt;config.pl&lt;/tt&gt;, the inaccessibility of lexical variables is no longer a problem. Besides that, the code looks very clean and we have a very powerful config file format that automatically supports comments and all kinds of useful functions. How about &lt;tt&gt;interval =&gt; 24 * 60 * 60,&lt;/tt&gt; for self-documentation? :)&lt;/p&gt;&lt;h2&gt;Still not good enough&lt;/h2&gt;&lt;p&gt;[do] updates &lt;tt&gt;%INC&lt;/tt&gt;, which you may or may not want. To avoid this, use [eval] [cpan://File::Slurp|read_file] instead. To find out if you want this, read [perlvar].&lt;/p&gt;&lt;p&gt;There is a way to get an &lt;tt&gt;include()&lt;/tt&gt; the way other languages have it. This is a very ugly hack that uses an internal exception made for Perl&#39;s debugger, and is possibly not future proof. As said before, you should not want to include a file. Still, because it is possible, I feel I have to tell you how. Just don&#39;t actually use it.&lt;/p&gt;&lt;p&gt;If you read the documentation for [eval] (which you of course should (don&#39;t use an operator without having read its documentation first)), you see that if it is called from within the &lt;tt&gt;DB&lt;/tt&gt; package, it is executed in the caller&#39;s scope. This means that lexical values are made visible and the file behaves as a code block.&lt;/p&gt;&lt;p&gt;Here is an example to get an &lt;tt&gt;include()&lt;/tt&gt; function that actually works the way most people expect:&lt;pre class=&quot;block_code&quot;&gt;use strict;package Acme::Include;use base &#39;Exporter&#39;;use File::Slurp ();our @EXPORT = &#39;include&#39;;{    package DB;    # The sub&#39;s name is fully qualified to avoid getting a B::Include    sub Acme::Include::include ($) {        my ($filename) = @_;        my $code = qq[#line 1 &quot;$filename&quot;\n] .            File::Slurp::read_file($filename);        eval $code;    }}1;&lt;/pre&gt;Documentation for the &lt;tt&gt;#line&lt;/tt&gt; directive is in [perlsyn].&lt;/p&gt;&lt;p&gt;To test this new module, save it as Acme/Include.pm and create:&lt;pre class=&quot;block_code&quot;&gt;# This is foo.pluse strict;use Acme::Include;my $lexical = &#39;set in foo.pl&#39;;include &#39;bar.pl&#39;;print $lexical;  # Should print: set in bar.pl&lt;/pre&gt;and:&lt;pre class=&quot;block_code&quot;&gt;# This is bar.pluse strict;$lexical = &#39;set in bar.pl&#39;;# There is no &quot;my&quot; here, because that would create a *new* lexical# variable, hiding the existing one.&lt;/pre&gt;and then run &lt;tt&gt;perl foo.pl&lt;/tt&gt;.&lt;/p&gt;&lt;p&gt;This example Acme::Include does not have any error checking. In practice, you will want to check &lt;tt&gt;$@&lt;/tt&gt; somewhere (but you also want to retain the value returned by the included file, and context to propagate properly. Good luck!).&lt;/p&gt;&lt;h2&gt;Learning more&lt;/h2&gt;&lt;p&gt;I wrote this tutorial to have an answer ready for the &lt;i&gt;n&lt;/i&gt;th time someone in EFnet&#39;s #perlhelp asks why [require] works only once, or asks how to really include a file. Explaining the same thing over and over gets annoying over time. This is not a good guide to writing modules. For that, read chapter 10 of [http://learn.perl.org/library/beginning_perl/|Beginning Perl] and [perlmod] and [perlnewmod]. Of course, good code always comes with good documentation; so learn [id://252477].&lt;/p&gt;&lt;h2&gt;One last thing&lt;/h2&gt;&lt;p&gt;If you name your module &lt;tt&gt;Test&lt;/tt&gt;, don&#39;t be surprised if it doesn&#39;t work. The current working directory comes &lt;b&gt;last&lt;/b&gt; in &lt;tt&gt;@INC&lt;/tt&gt;, so the [perldoc://Test] module that is in the Perl distribution is probably loaded instead. This bites me at least once per year, this time while writing this tutorial :).&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>Accessing Microsoft SQL Server from Linux using DBD::Sybase (CleverFox)</title>
    <link>http://prlmnks.org/html/392385.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/392385.html</guid>

    <description>
        &lt;p&gt;&lt;font face=&quot;Verdana&quot; size=&quot;5&quot;&gt;Accessing Microsoft SQL Server from Perl&lt;/font&gt;&lt;font face=&quot;Verdana&quot;&gt;&lt;br&gt;by Lindsay Leeds (2004 Sep 20)&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;Recently, I made yet another attempt to get Perl to access Microsoft SQL Server using DBD.&amp;nbsp; Usually, when I want to connect to a Microsoft SQL Server, it is from Perl on Windows.&amp;nbsp; So I take the easy route and use DBD::ODBC and use an ODBC connection.&amp;nbsp; This time though, I wanted to connect to Microsoft SQL Server 2000 from a Linux box.&amp;nbsp; Having no ODBC to fall back on, I looked for native DBD driver of some sort.&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;It took me several hours of struggling to make it work.&amp;nbsp; I almost gave up several times, so I am writing outline to help anyone else trying to accomplish this same task.&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;In the end, we will use the DBD::Sybase perl module from CPAN to access the Microsoft SQL Server.&amp;nbsp; Before we can do that however, we must first compile the freetds library.&lt;br&gt;&lt;br&gt;Note: From now on I will refer to Microsoft SQL Server as SQL Server.&amp;nbsp; Please do not confuse this with a generic sql server.&amp;nbsp; We can all now pause to gripe about the lack of imagination in product naming at Microsoft.&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot; size=&quot;4&quot;&gt;Compiling Freetds&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;Download and compile freetds from&lt;a href=&quot;http://www.freetds.org/&quot;&gt;http://www.freetds.org/&lt;/a&gt;.&lt;br&gt;&lt;br&gt;once you unzip and untar it, enter the directory and run:&lt;/font&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;font face=&quot;Courier New&quot;&gt;./configure --prefix=/usr/local/freetds --with-tdsver=7.0&lt;br&gt;make&lt;br&gt;make install&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot; size=&quot;4&quot;&gt;Configuring Freetds&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;Now we have the freetds compiled, but we still have configure it.&amp;nbsp; This is the part that threw me off and is so different from other DBD drivers.&amp;nbsp; The DBD::Sybase driver will ultimately be affected by the contents of the /usr/local/freetds/etc/freetds.conf file.&amp;nbsp; &lt;b&gt;If that file is not configured correctly, your DBD::Sybase connection will fail.&lt;/b&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;Okay, now that we have established there is a&amp;nbsp; relationship between the freetds.conf file and the DBD::Sybase module, let&#39;s edit the freetds.conf file.&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;The strategic modifications I made to the freetds.conf file were:&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;1) uncomment the following lines and modify if necessary:&lt;/font&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;font face=&quot;Courier New&quot;&gt;try server login = yes&lt;br&gt;try domain login = no&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;Note: this forces the module to attempt a database login instead of a domain login.&amp;nbsp; I could not get domain login to work, though I will admit I did not try very hard.&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;2) uncomment the following line and modify if necessary:&lt;/font&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;font face=&quot;Courier New&quot;&gt;tds version = 7.0&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;This supposedly sets the default tds version to establish a connection with.&amp;nbsp; I have only SQL Server 2000 servers, and they won&#39;t talk at any lower version.&amp;nbsp; So I set it to 7.0.&amp;nbsp; If for some reason you had older SQL Servers, you might leave it at the default 4.2.&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;3) create a server entry for my server sql1:&lt;/font&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;/font&gt;&lt;pre class=&quot;block_code&quot;&gt;[sql1]host = sql1port = 1433tds version = 8.0&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;Note: My server here is sql1.&amp;nbsp; Ping sql1 worked, so I am sure I can resolve it using DNS.&amp;nbsp; You can also specifcy an ip address instead of the host name.&amp;nbsp; The sql1 in the brackets is just a descriptor.&amp;nbsp; It could be &#39;superduperserver&#39; and it would still work as long as my &#39;host =&#39; is set correctly.&amp;nbsp; I tried &#39;tds version 7.0&#39; for my SQL Sever 2000 and it worked.&amp;nbsp; Version 5.0 though resulted in an error.&amp;nbsp; You might want to verify your SQL Server is listening on port 1433 with a &#39;netstat -a -n&#39; run from the command line on the SQL Server.&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;At this point you can verify your configuration.&lt;/font&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;font face=&quot;Courier New&quot;&gt;/usr/local/freetds/bin/tsql -S sql1 -U sqluser&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;You will then be prompted for a password and if everything is well, you will see a &#39;1)&#39; waiting for you to enter a command.&amp;nbsp; If you can&#39;t get the 1) using tsql, I doubt your DBD::Sybase perl code is going to work.&amp;nbsp; Please note that sqluser is not an Active Directory/Windows Domain user, but an SQL Server user.&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot; size=&quot;4&quot;&gt;Compiling DBD::Sybase&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;Now that we have the freetds library prerequisite for DBD::Sybase installed and configured, we can compile the DBD::Sybase perl module.&amp;nbsp; Obtain it from &lt;a href=&quot;http://www.cpan.org&quot;&gt;www.cpan.org&lt;/a&gt; if you haven&#39;t already.&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;once you have untarred it and are in the directory, run:&lt;/font&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;export SYBASE=/usr/local/freetds&lt;br&gt;perl Makefile.PL&lt;br&gt;make&lt;br&gt;make install&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;Note: The export line is to let the compilation process know where to find the freetds libraries.&lt;br&gt;&lt;br&gt;&lt;/font&gt;&lt;font face=&quot;Verdana&quot; size=&quot;4&quot;&gt;Using DBD::Sybase&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;You are now ready to test your DBD::Sybase module.&lt;/font&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;font face=&quot;Courier&quot;&gt;#!/usr/bin/perl&lt;br&gt;&lt;br&gt;use DBI;&lt;br&gt;&lt;br&gt;$dsn = &#39;DBI:Sybase:server=sql1&#39;;&lt;br&gt;&lt;br&gt;my $dbh = DBI-&amp;gt;connect($dsn, &amp;quot;sqluser&amp;quot;, &#39;password&#39;);&lt;br&gt;die &amp;quot;unable to connect to server $DBI::errstr&amp;quot; unless $dbh;&lt;br&gt;&lt;br&gt;$dbh-&amp;gt;do(&amp;quot;use mydatabase&amp;quot;);&lt;br&gt;&lt;br&gt;$query = &amp;quot;SELECT * FROM MYTABLE&amp;quot;;&lt;br&gt;$sth = $dbh-&amp;gt;prepare ($query) or die &amp;quot;prepare failed\n&amp;quot;;&lt;br&gt;$sth-&amp;gt;execute( ) or die &amp;quot;unable to execute query $query&amp;nbsp;&amp;nbsp; error $DBI::errstr&amp;quot;;&lt;br&gt;&lt;br&gt;$rows = $sth-&amp;gt;rows ;&lt;br&gt;print &amp;quot;$row rows returned by query\n&amp;quot;;&lt;br&gt;&lt;br&gt;while ( @first = $sth-&amp;gt;fetchrow_array ) {&lt;br&gt;&amp;nbsp;&amp;nbsp; foreach $field (@first) {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;quot;field: $field\n&amp;quot;;&lt;br&gt;&amp;nbsp;&amp;nbsp; }&lt;br&gt;}&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;Good luck!&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;&lt;br&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;&lt;br&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;&lt;br&gt;&lt;br&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>Calling .NET Assemblies with Win32::OLE (InfiniteSilence)</title>
    <link>http://prlmnks.org/html/392275.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/392275.html</guid>

    <description>
        This is a tutorial for calling a .NET assembly via Win32::OLE. I was looking for such a tutorial on the web and previously at PerlMonks but didn&#39;t find anything, so I elected to research the issue, get a quick example working, and submit it.&lt;P&gt;Basically what you want to be able to do is:&lt;pre class=&quot;block_code&quot;&gt;perl -e &quot;use Win32::OLE; $hl = new Win32::OLE(&#39;HelloDot.HelloWorld&#39;) or die $!; $hl-&gt;SayHello();&quot;&lt;/pre&gt;Where &lt;b&gt;HelloDot.HelloWorld&lt;/b&gt; is a .NET assembly registered in the system to look/act/smell like a regular COM component. The following are preliminary setup steps that do not require explanation:&lt;P&gt;&lt;li&gt;Step 1: You will have to install both the .NET Framework and the .NET SDK on your machine (type .net framework/sdk download in Google)&lt;li&gt;Step 2: The installer does not set your path, so you will have to add the following to be able to reach gacutil.exe, regasm.exe, csc.exe (my cheezy example was written in C#), etc.: C:\Program Files\Microsoft.NET\SDK\v1.1\Bin\;C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\&lt;P&gt;After mucking with your PATH, you should create a key file like this:&lt;pre class=&quot;block_code&quot;&gt;sn -k personality.snk&lt;/pre&gt;This creates a &#39;key pair&#39; file which contains a public &lt;i&gt;and&lt;/i&gt; a private key for entering the .dll we are about to create into the GAC, the Global Assembly Cache. Think of it as a Windows registry for .NET assemblies. There is a way to separate the public key part from the private one (using sn -p) in case you are interested. (Note: I&#39;m not sure why this thing didn&#39;t offer to allow me a choice of ciphers or allow me to choose my own entropy engine. I remember reading that it is using SHA1 or something, but I don&#39;t know.)&lt;P&gt;The first think you will notice when you run an example with the .NET framework is that it is terribly slow. A simple &#39;Hello World&#39; takes about three seconds to run every time. It seems obvious to me that this thing was not written for quick one-liner-like execution, so be warned. Copy the following hello.cs file and compile it:&lt;pre class=&quot;block_code&quot;&gt; using System;using System.Reflection;[assembly:AssemblyVersion(&quot;1.0.0.0&quot;)][assembly:AssemblyKeyFile(&quot;personality.snk&quot;)]namespace HelloDot {  public class HelloWorld {   public HelloWorld(){    //no param constructor for COM   }   public void SayHello(){     Console.WriteLine(&quot;Hello from DOT NET&quot;);   }  }}&lt;/pre&gt;You need a constructor with no params for the .NET assembly to be called like a regular COM component (as with Win32::OLE). There is some kind of wrapper that M$soft creates to allow COM components to interact with .NET assemblies and the constructor is necessary to make that happen. If you are interested on the why, more information on that is &lt;a href=&quot;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnofftalk/html/office11012001.asp&quot;&gt;here&lt;/a&gt;. The only problem with this is that a third party .dll is probably not going to have this constructor, so at that point you will have to create a wrapper class that &lt;i&gt;does&lt;/i&gt; have it before you try this.&lt;P&gt;Anyway, you need to compile this into a .dll like so:&lt;pre class=&quot;block_code&quot;&gt;csc /t:library /out:hellodot.dll hello.cs&lt;/pre&gt;If you go back to to the hello.cs code, you will notice the funny lines before the namespace that stand out like a sore thumb: &lt;b&gt;assembly:AssemblyVersion...yadda,yadda&lt;/b&gt;. These instructions tell the compiler that you are creating an assembly you are intending to share. If you remove the lines and recompile you will notice that the .dll becomes a little smaller. Remember to put it back in and recompile before you continue this tutorial.&lt;P&gt;If the .dll compiled okay you now have to register it:&lt;pre class=&quot;block_code&quot;&gt; gacutil /i hellodot.dll&lt;/pre&gt;There is one more thing to do. Your .NET assembly still needs to look and act like a regular COM component. Normal COM components (i.e. Excel.Application, Microsoft.XML, etc.) are registered with regsvr32. This puts their GUIDs in the Window&#39;s Registry (see HKEY_LOCAL_MACHINE/Software/Classes for the ones you&#39;ve got). Not so in this case. You need to use regasm.exe in order to &#39;register&#39; your .NET .dll to be usable by everybody outside of the .NET camp:&lt;pre class=&quot;block_code&quot;&gt;regasm hellodot.dll&lt;/pre&gt;With all of this being done, you should be able to call the following:&lt;pre class=&quot;block_code&quot;&gt;perl -e &quot;use Win32::OLE; $hl = new Win32::OLE(&#39;HelloDot.HelloWorld&#39;) or die $!; $hl-&gt;SayHello();&quot;&lt;/pre&gt;&lt;P&gt;You may read from various online sources that it is unncessary to load the assembly into the GAC for you to call it as a COM component, but this does not (at least for me) seem to work. Without registering in the GAC I had to copy the .dll to the Windows/System32 directory just to get it to work for the Window&#39;s Scripting Host. Win32::OLE simply could not find the bugger until I registered it in the GAC.&lt;P&gt;&lt;B&gt;Summary:&lt;/B&gt;&lt;br&gt;&amp;nbsp;&lt;BR&gt;Are you are asking yourself, &quot;why is any of this important?&quot; Well, it seems that the only other way to get Perl on Windows to interact with .NET is to pony up cash for Visual Studio.NET and &lt;a href=&quot;www.activestate.com&quot;&gt;Visual Perl&lt;/a&gt;. The above tutorial offers a (relatively) quick and (depending on your threshold) painless way to interoperate with .NET components.
    </description>
</item>

        

<item>
    <title>Troubleshooting Perl CGI scripts (brian_d_foy)</title>
    <link>http://prlmnks.org/html/380424.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/380424.html</guid>

    <description>
        &lt;p&gt;This resource is intended as a general framework for working throughproblems with CGI scripts.  It is not a complete guide to everyproblem that you may encounter, nor a tutorial on bug squashing.  Itis just the culmination of my experience debugging CGI scripts for tenyears.  This page seems to have had many different homes, and I seemto forget it exists, so I&#39;m adding it to the Monastery&#39;s canon. Youcan send any comments or suggestions to me at &lt;ahref=&quot;mailto:comdog@panix.com&quot;&gt;comdog@panix.com&lt;/a&gt;. You may alsowant to see the &lt;a href=&quot;http://www.perl.org/CGI_MetaFAQ.html&quot;&gt;CGIMeta FAQ&lt;/a&gt; for a list of references.&lt;/p&gt;&lt;hr&gt;&lt;dl&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Are you using Perl&#39;s built in features to help you find problems?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;If you have not turned on warnings with the -w switch and are not usingstrict, you should be.  These things help you find problems.  You may needa bit of time to get used to them, but they save you many hours of time.You need them to go through this troubleshooting procedure.  &lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Did you output a valid CGI header first?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;The server is expecting the first output from a CGIscript to be the CGI header.  Typically that might be assimple as &lt;tt class=&quot;inline_code&quot;&gt;print &quot;Content-type: text/plain\n\n&quot;;&lt;/tt&gt;or with CGI.pm and its derivatives, &lt;pre class=&quot;block_code&quot;&gt;printheader()&lt;/pre&gt;.  Some servers are sensitive to error output(on STDERR) showing up before standard output (on STDOUT).&lt;/dd&gt;  &lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;What did the error log say?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;Servers keep error logs (or they should, at least). Error output from the server and from your script shouldshow up there.  Find the error log and see what it says.There isn&#39;t a standard place for log files.  Look in the server configuration for their location, or ask the serveradmin.  You can also use tools such as &lt;tt class=&quot;inline_code&quot;&gt;CGI::Carp&lt;/tt&gt;to keep your own log files.  &lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;What are the scripts permissions?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;If you see errors like &amp;quot;Permission denied&amp;quot; or &amp;quot;Method notimplemented&amp;quot;, it probably means that your script is notreadable and executable by the web server user.  On flavorsof Unix, changing the mode to 755 is recommended:&lt;tt class=&quot;inline_code&quot;&gt;chmod 755 filename&lt;/tt&gt;. &lt;fontcolor=&quot;#FF0000&quot;&gt;Never set a mode to 777!&lt;/font&gt;&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Are you using &lt;tt class=&quot;inline_code&quot;&gt;use strict&lt;/tt&gt;?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;Remember that Perl automatically creates variables whenyou first use them.  This is a feature, but sometimes cancause bugs if you mistype a variable name.  The pragma&lt;tt class=&quot;inline_code&quot;&gt;use strict&lt;/tt&gt; will help you find those sorts oferrors.  It&#39;s annoying until you get used to it, but yourprogramming will improve significantly after awhile andyou will be free to make different mistakes.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Does the script compile?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;You can check for compilation errors by using the -cswitch.  Concentrate on the first errors reported.  Rinse,repeat. If you are getting really strange errors, check toensure that your script has the right line endings.  If youFTP in binary mode, checkout from CVS, or something else thatdoes not handle line end translation, the web server may seeyour script as one big line.  Transfer Perl scripts in ASCIImode.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Does the script give you warnings?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;You can check for warnings by using the -w switch whichI recommend you use during all development.  Warnings arefully explained in the perldiag man page, or by using thepragma &lt;tt class=&quot;inline_code&quot;&gt;use diagnostics;&lt;/tt&gt;.  If you make yourscript &amp;quot;-w clean&amp;quot; you will have less trouble withit in the future.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Is the script complaining about insecure dependencies?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;If your script complains about insecure dependencies, you are probably using the -T switch to turn on taint mode, which isa good thing since it keeps you have passing unchecked data to the shell. Ifit is complaining it is doing its job to help us write more secure scripts. Anydata originating from outside of the program (i.e. the environment)is considered tainted.  Environment variables such as PATH and LD_LIBRARY_PATHare particularly troublesome.  You have to set these to a safe valueor unset them completely, as I recommend.  You should be using absolutepaths anyway.  If taint checking complains about something else,make sure that you have untainted the data.  See the perlsecman page for details.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;What happens when you run it from the command line?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;Does the script output what you expect when run from thecommand line?  Is the header output first, followed by ablank line?  Remember that &lt;tt class=&quot;inline_code&quot;&gt;STDERR&lt;/tt&gt; may be merged with &lt;tt class=&quot;inline_code&quot;&gt;STDOUT&lt;/tt&gt;if you are on a terminal (e.g. an interactive session), anddue to buffering may show up in a jumbled order.  Turn onPerl&#39;s autoflush feature by setting &lt;tt class=&quot;inline_code&quot;&gt;$|&lt;/tt&gt; to atrue value. Typically you might see &lt;tt class=&quot;inline_code&quot;&gt;$|++;&lt;/tt&gt; inCGI programs.  Once set, every print and write willimmediately go to the output rather than being buffered.You have to set this for each filehandle.  Use &lt;tt class=&quot;inline_code&quot;&gt;select&lt;/tt&gt; tochange the default filehandle, like so:&lt;blockquote&gt;&lt;pre class=&quot;block_code&quot;&gt;$|++;                            #sets $| for STDOUT$old_handle = select( STDERR );  #change to STDERR$|++;                            #sets $| for STDERRselect( $old_handle );           #change back to STDOUT&lt;/pre&gt;&lt;/blockquote&gt;Either way, the first thing output should be the CGI headerfollowed by a blank line.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;What happens when you run it from the command line with a CGI-like environment?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;The web server environment is usually a lot more limitedthan your command line environment, and has extrainformation about the request.  If your script runs finefrom the command line, you might try simulating a web serverenvironment.  If the problem appears, you have anenvironment problem.&lt;p&gt;Unset or remove these variables&lt;/p&gt;&lt;ul&gt;&lt;li&gt;PATH&lt;li&gt;LD_LIBRARY_PATH&lt;li&gt;all ORACLE_* variables&lt;/ul&gt;&lt;p&gt;Set these variables&lt;/p&gt;&lt;ul&gt;&lt;li&gt;REQUEST_METHOD (set to GET, HEAD, or POST as appropriate)&lt;li&gt;SERVER_PORT (set to 80, usually)&lt;li&gt;REMOTE_USER (if you are doing protected access stuff)&lt;/ul&gt;Recent versions of CGI.pm ( &gt; 2.75 ) require the -debug flag to get the old (useful) behavior, so you might have to add it toyour CGI.pm imports.&lt;pre class=&quot;block_code&quot;&gt;use CGI qw(-debug)&lt;/pre&gt;&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Are you using &lt;tt class=&quot;inline_code&quot;&gt;die()&lt;/tt&gt; or &lt;tt class=&quot;inline_code&quot;&gt;warn()&lt;/tt&gt;?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;Those functions print to &lt;tt class=&quot;inline_code&quot;&gt;STDERR&lt;/tt&gt; unless you have redefined them.  They don&#39;t output a CGI header, either.  You can getthe same functionality with packages such as &lt;tt class=&quot;inline_code&quot;&gt;CGI::Carp&lt;/tt&gt;.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;What happens after you clear the browser cache?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;If you think your script is doing the right thing, andwhen you perform the request manually you get the rightoutput, the browser might be the culprit.  Clear the cacheand set the cache size to zero while testing.  Remember thatsome browsers are really stupid and won&#39;t actually reloadnew content even though you tell it to do so.  This isespecially prevalent in cases where the URL path is thesame, but the content changes (e.g. dynamic images).&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Is the script where you think it is?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;The file system path to a script is not necessarilydirectly related to the URL path to the script.  Make sureyou have the right directory, even if you have to write ashort test script to test this.  Furthermore, are you surethat you are modifying the correct file?  If you don&#39;t seeany effect with your changes, you might be modifying adifferent file, or uploading a file to the wrong place. (This is, by the way, my most frequent cause of such trouble;)&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Are you using &lt;tt class=&quot;inline_code&quot;&gt;CGI.pm&lt;/tt&gt;, or a derivative of it?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;If your problem is related to parsing the CGI input and youaren&#39;t using a widely tested module like &lt;tt class=&quot;inline_code&quot;&gt;CGI.pm&lt;/tt&gt;, &lt;tt class=&quot;inline_code&quot;&gt;CGI::Request&lt;/tt&gt;, or&lt;tt class=&quot;inline_code&quot;&gt;CGI::Lite&lt;/tt&gt;, use the module and get on with life.  &lt;tt class=&quot;inline_code&quot;&gt;CGI.pm&lt;/tt&gt; has a &lt;tt class=&quot;inline_code&quot;&gt;cgi-lib.pl&lt;/tt&gt; compatibility mode which can help you solve inputproblems due to older CGI parser implementations.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Did you use absolute paths?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;If you are running external commands with&lt;tt class=&quot;inline_code&quot;&gt;system()&lt;/tt&gt;, back ticks, or other IPC facilities,you should use an absolute path to the external program. Not only do you know exactly what you are running, but youavoid some security problems as well.  If you are openingfiles for either reading or writing, use an absolute path. The CGI script may have a different idea about the currentdirectory than you do.  Alternatively, you can do anexplicit &lt;tt class=&quot;inline_code&quot;&gt;chdir()&lt;/tt&gt; to put you in the right place.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Did you check your return values?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;Most Perl functions will tell you if they worked or notand will set &lt;tt class=&quot;inline_code&quot;&gt;$!&lt;/tt&gt; on failure.  Did you check thereturn value and examine &lt;tt class=&quot;inline_code&quot;&gt;$!&lt;/tt&gt; for error messages? Did you check&lt;tt class=&quot;inline_code&quot;&gt;$@&lt;/tt&gt; if you were using &lt;tt class=&quot;inline_code&quot;&gt;eval&lt;/tt&gt;?&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Which version of Perl are you using?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;The latest stable version of Perl is 5.8.3.  Are you using an olderversion?  Different versions of Perl may have different ideas of warnings.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Which web server are you using?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;Different servers may act differently in the samesituation.  The same server product may act differently withdifferent configurations. Include as much of thisinformation as you can in any request for help.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Did you check the server documentation?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;Serious CGI programmers should know as much about theserver as possible - including not only the server featuresand behavior, but also the local configuration. Thedocumentation for your server might not be available to youif you are using a commercial product.  Otherwise, thedocumentation should be on your server.  If it isn&#39;t, lookfor it on the web.  Consult the &lt;ahref=&quot;http://www.perl.org/CGI_MetaFAQ.html&quot;&gt;CGIMeta FAQ&lt;/a&gt; for a list of references.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Did you search the archives of comp.infosystems.www.authoring.cgi?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;It&#39;s likely that someone has had your problem before,and that someone (possibly me) has answered it in thisnewsgroup. &lt;a href=&quot;http://groups.google.com&quot;&gt;Archives are available from Google&lt;/a&gt;&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Can you reproduce the problem with a short test script?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;In large systems, it may be difficult to track down a bugsince so many things are happening.  Try to reproduce the problembehavior with the shortest possible script.  Knowing the problemis most of the fix.  This may be certainly time-consuming, but youhaven&#39;t found the problem yet and you&#39;re running out of options. :)&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Did you decide to go see a movie?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;Seriously.  Sometimes we can get so wrapped up in the problem that wedevelop &amp;quot;perceptual narrowing&amp;quot; (tunnel vision).  Taking a break,getting a cup of coffee, or blasting some bad guys in Quake might give youthe fresh perspective that you need to re-approach the problem.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Have you vocalized the problem?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;Seriously again.  Sometimes explaining the problem aloudleads us to our own answers.  Talk to the penguin (plush toy) becauseyour co-workers aren&#39;t listening.  If you are interested in thisas a serious debugging tool (and I do recommend it if you haven&#39;t found the problem by now), you might also like to read &lt;ahref=&quot;http://www.amazon.com/exec/obidos/ASIN/0932633420/perlmongers01&quot;&gt;The Psychologyof Computer Programming&lt;/a&gt;.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- ########################## --&gt;&lt;dt&gt;&lt;b&gt;Did you post an informative and well-developed question to comp.infosystems.www.authoring.cgi?&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;Once you have gone through all of these steps, youshould have all of the information to ask a question thatcan elicit a good answer.  Post in as much detail aspossible, and include the smallest bit of code thatreproduces the problem.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;/dl&gt;&lt;!-- Node text goes above. Div tags should contain sig only --&gt;&lt;div class=&quot;pmsig&quot;&gt;&lt;div class=&quot;pmsig-366986&quot;&gt;-- &lt;br /&gt;brian d foy &lt;bdfoy@cpan.org&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;font size=-2&gt;Edited by &lt;a href=&quot;/out/node/davido&quot;&gt;davido&lt;/a&gt;: Fixed HTML and formatting to eliminate horizontal scrolling in IE.&lt;/font&gt;&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>Installing Perl on a Windows PC (giricredwolf)</title>
    <link>http://prlmnks.org/html/378226.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/378226.html</guid>

    <description>
        First, go to &lt;a href=&quot;http://www.activeperl.com&quot;&gt;ActiveState&#39;s ActivePerl Site&lt;/a&gt;, http://www.activeperl.com.  From here you can either click on the &quot;Perl&quot; link in the top banner, or hover your mouse pointer over &quot;Languages&quot; in the red bar and then click on &quot;ActivePerl Family&quot; in the dropbox that appears.  On the next page, click on &quot;ActivePerl&quot; under &quot;ActivePerl Family&quot;.  (You&#39;re getting close.  Don&#39;t give up yet!)  At the bottom of the page, click &quot;DOWNLOAD&quot;, then either fill in the blanks on the next page or not and click &quot;Next&quot;.  (ActiveState doesn&#39;t require contact info.)&lt;p&gt;This page gives you several options.  The first thing you should do is check out the &quot;minimum requirements&quot; link in the middle column.  (The three columns being the download list, an info column, and then the &quot;Register... Download&quot; column.  If you&#39;re running Windows XP, you&#39;re set and don&#39;t really need to worry about this.  The left column should say &quot;ActivePerl&quot; and then a version number.  Choose the most recent version and download the MSI package under the Windows heading.&lt;p&gt;BEFORE CONTINUING:  Make sure you have Administrator privileges on your computer.  If you don&#39;t, you&#39;ll have more work to do after installing.&lt;p&gt;Simply run the MSI (an executable) and follow the installation guidelines.  If, for one reason or another, you cannot install from the MSI, go back to ActivePerl&#39;s web space and download the AS package (a .zip file).  The ActivePerl site explicitly states, &quot;The Windows AS Package provides NO uninstall functionality, and is recommended only if you are unable to install ActivePerl using the MSI installer.&quot;  (What this basically means is that you&#39;ll have to manually uninstall it if you ever want to get rid of it.)&lt;p&gt;You can now write Perl programs in any text editor (like Notepad, but turn wordwrap off) and run them through the Command Prompt using the &quot;perl&quot; command, just like all the other OSes.  (Command Prompt is in Start &gt; All Programs &gt; Accessories OR Start &gt; Programs &gt; Accessories for non-XP systems.)&lt;p&gt;This should work for any version of Windows.  Please be sure to check the system requirements listed on ActiveState&#39;s download page to be sure your machine/OS can handle it.&lt;p&gt;Good luck!&lt;p&gt;ADDENDUM&lt;br&gt;ActivePerl is not the only Perl for Windows out there, it is simply the first that I came accross.  As noted by &lt;a href=&quot;/html/157432.html&quot;&gt;Joost&lt;/a&gt;, there is also &lt;a href=&quot;http://www.cygwin.com&quot;&gt;CygWin&lt;/a&gt; at http://www.cygwin.com (directions listed in his reply below).  CygWin is basically, for all intents and puposes, a Linix shell emulator for PC.  See their site for more details.&lt;p&gt;I also want to mention a very helpful tool for me when writing is the VI Improved (VIM) text editor, available at &lt;a href=&quot;http://www.vim.org/&quot;&gt;http://www.vim.org/&lt;/a&gt;.  It&#39;s free and has many features to help you with coding, including (but not limited to) auto-indenting, color highlighting, and multiple computer language support.  VIM is what I learned on in school, used when I had Linux, and is a great tool even on a Windows based machine.&lt;p&gt;Last update 2004.07.31.0150
    </description>
</item>

        

<item>
    <title>The Scalar Range Operator (pbeckingham)</title>
    <link>http://prlmnks.org/html/377450.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/377450.html</guid>

    <description>
        &lt;h2&gt;The Scalar Range Operator&lt;/h2&gt;&lt;p&gt;I have been playing with the scalar range operator, and it confused me so much that I started experimenting and reading about it,and here is what I wrote up.&lt;/p&gt;&lt;p&gt;&lt;h3&gt;Numeric Values&lt;/h3&gt;This operator, in scalar context, has two forms that act as a bistable or flip-flop.  The first form looks like this:&lt;pre class=&quot;block_code&quot;&gt;  if ($left .. $right)  {    ...  }&lt;/pre&gt;This &lt;tt class=&quot;inline_code&quot;&gt;if&lt;/tt&gt; statement works as follows:The condition evaluates false until &lt;tt class=&quot;inline_code&quot;&gt;$left&lt;/tt&gt; evaluates true.Then the &lt;tt class=&quot;inline_code&quot;&gt;$left&lt;/tt&gt; condition is ignored, and the condition continuesto evaluate true until &lt;tt class=&quot;inline_code&quot;&gt;$right&lt;/tt&gt; evaluates true, at which pointthe condition evaluates false, and it goes back to check &lt;tt class=&quot;inline_code&quot;&gt;$left&lt;/tt&gt;.In this way, it flip-flops between waiting for the left side to evaluate true,and then waiting for the right side to evaluate true.  Very strange, untilyou see it operating in a program:&lt;pre class=&quot;block_code&quot;&gt;  while (&lt;DATA&gt;)  {    print if 2 .. 4;  }  __DATA__  first  second  third  fourth  fifth  __OUTPUT__  second  third  fourth&lt;/pre&gt;This program prints out the second and third line of the data.A numeric value in the scalar range operator is therefore compared to&lt;tt class=&quot;inline_code&quot;&gt;$.&lt;/tt&gt;.&lt;/p&gt;&lt;p&gt;&lt;h3&gt;Regular Expressions&lt;/h3&gt;This example shows the use of two regular expressions in the scalarrange operator:&lt;pre class=&quot;block_code&quot;&gt;  while (&lt;DATA&gt;)  {    print if /start/ .. /end/;  }  __DATA__  ignore  start  first  second  third  end  ignore  start  fourth  fifth  end  ignore  __OUTPUT__  start  first  second  third  end  start  fourth  fifth  end&lt;/pre&gt;It prints out lines in the data beginning with the line that first evaluatestrue (&lt;tt class=&quot;inline_code&quot;&gt;start&lt;/tt&gt;), until the line that next evaluates true(&lt;tt class=&quot;inline_code&quot;&gt;end&lt;/tt&gt;).  All the lines that are not bracked by &lt;tt class=&quot;inline_code&quot;&gt;start/end&lt;/tt&gt;pairs are ignored.  Note that this data contains two blocks of lines that are between &lt;tt class=&quot;inline_code&quot;&gt;start&lt;/tt&gt; and &lt;tt class=&quot;inline_code&quot;&gt;end&lt;/tt&gt; markers, and the lines outside those ranges are ignored.&lt;/p&gt;&lt;p&gt;&lt;h3&gt;Numeric and Regular Expressions&lt;/h3&gt;Combining a numeric and a regex in the range operator also works as expected.In this example, the lines from &lt;tt class=&quot;inline_code&quot;&gt;$. == 1&lt;/tt&gt; until &lt;tt class=&quot;inline_code&quot;&gt;$_ =~ /end/&lt;/tt&gt;are printed.&lt;pre class=&quot;block_code&quot;&gt;  while (&lt;DATA&gt;)  {    print if 2 .. /end/;  }  __DATA__  first  second  third  end  ignore  __OUTPUT__  second  third  end&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;&lt;h3&gt;Exluding Markers&lt;/h3&gt;In order to exclude lines that contain &lt;tt class=&quot;inline_code&quot;&gt;start&lt;/tt&gt; and &lt;tt class=&quot;inline_code&quot;&gt;end&lt;/tt&gt;,a further condition is required.  The condition is that the result returned bythe scalar range operator must be neither &lt;tt class=&quot;inline_code&quot;&gt;1&lt;/tt&gt; (representing&lt;tt class=&quot;inline_code&quot;&gt;$.&lt;/tt&gt; of 1), nor must it contain &lt;tt class=&quot;inline_code&quot;&gt;E&lt;/tt&gt;.  When the operatorencounters the line that evaluates true for the right-hand-side, it&#39;s returnvalue is (in the example below) &lt;tt class=&quot;inline_code&quot;&gt;5E0&lt;/tt&gt;.  This number evaluates to&lt;tt class=&quot;inline_code&quot;&gt;5&lt;/tt&gt;, but contains that &lt;tt class=&quot;inline_code&quot;&gt;E&lt;/tt&gt;, which is the indicator thatthis line terminates the right-hand-side of the operator.This code prints all the lines &lt;i&gt;between&lt;/i&gt; the &lt;tt class=&quot;inline_code&quot;&gt;start&lt;/tt&gt; and&lt;tt class=&quot;inline_code&quot;&gt;end&lt;/tt&gt; lines:&lt;pre class=&quot;block_code&quot;&gt;  while (&lt;DATA&gt;)  {    if (my $num = /start/ .. /end/)    {      print unless $num == 1 || $num =~ /E/;    }  }  __DATA__  ignore  start  first  second  third  end  ignore  start  fourth  fifth  end  ignore  __OUTPUT__  first  second  third  fourth  fifth&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;To better illustrate that, this program prints out that value, for alllines between &lt;tt class=&quot;inline_code&quot;&gt;start&lt;/tt&gt; and &lt;tt class=&quot;inline_code&quot;&gt;end&lt;/tt&gt;:&lt;pre class=&quot;block_code&quot;&gt;  while (&lt;DATA&gt;)  {    if (my $num = /start/ .. /end/)    {      print $num, &quot;\t&quot;, $_;    }  }  __DATA__  ignore  start  first  second  third  end  ignore  start  fourth  fifth  end  ignore  __OUTPUT__  1       start  2       first  3       second  4       third  5E0     end  1       start  2       fourth  3       fifth  4E0     end&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;&lt;h3&gt;Markers on Same Line&lt;/h3&gt;This example places both the &lt;tt class=&quot;inline_code&quot;&gt;start&lt;/tt&gt; and &lt;tt class=&quot;inline_code&quot;&gt;end&lt;/tt&gt; tokenson the same line.  From the output, it can be seen that the combined linehas a value of &lt;tt class=&quot;inline_code&quot;&gt;1E0&lt;/tt&gt; which satisfies the test as both the firstand last line of the desired input.&lt;pre class=&quot;block_code&quot;&gt;  while (&lt;DATA&gt;)  {    if (my $num = /start/ .. /end/)    {      print $num, &quot;\t&quot;, $_;    }  }  __DATA__  ignore  start  first  second  end  ignore  start third end  ignore  __OUTPUT__  1       start  2       first  3       second  4E0     end  1E0     start third end&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;&lt;h3&gt;The Scalar ... Operator&lt;/h3&gt;The other form of the scalar range operator is &lt;tt class=&quot;inline_code&quot;&gt;...&lt;/tt&gt;. This operatorperforms as the &lt;tt class=&quot;inline_code&quot;&gt;..&lt;/tt&gt; operator does, but lines that meet one criteriaare not also evaluated for the other.So a line that contains both &lt;tt class=&quot;inline_code&quot;&gt;start&lt;/tt&gt; and &lt;tt class=&quot;inline_code&quot;&gt;end&lt;/tt&gt; is onlyevaluated once - in this case for the &lt;tt class=&quot;inline_code&quot;&gt;start&lt;/tt&gt; line, causing thisdata to be considered as having a &lt;tt class=&quot;inline_code&quot;&gt;start&lt;/tt&gt; but not an &lt;tt class=&quot;inline_code&quot;&gt;end&lt;/tt&gt;, meaning that the data is not properly treated in this example.&lt;pre class=&quot;block_code&quot;&gt;  while (&lt;DATA&gt;)  {    if (my $num = /start/ ... /end/)    {      print &quot;$num\t$_&quot;;    }  }  __DATA__  ignore  start first end  ignore  __OUTPUT__  1       start first end  2       ignore&lt;/pre&gt;This form of the scalar range operator is more efficient only if it is known that bothconditions can never be true on the same line.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; Changed examples to not include so many edge cases.  Thanks to [hossman].&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>Perl Idioms Explained - !!expr (broquaint)</title>
    <link>http://prlmnks.org/html/374287.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/374287.html</guid>

    <description>
        &lt;b&gt;Perl Idioms Explained - &lt;tt&gt;!!expr&lt;/tt&gt;&lt;/b&gt;&lt;pre class=&quot;block_code&quot;&gt;sub is_in_list {  return !!grep { $_ eq $_[0] } @_[ 1 .. $#_ ];}print &quot;baz is in list&quot;  if is_in_list &#39;baz&#39;, qw/ foo bar baz /;__output__baz is in list&lt;/pre&gt;Even though perl doesn&#39;t have a native boolean type, sometimes all aprogrammer wants is a nice simple boolean value, and this is what the&lt;tt&gt;!!expr&lt;/tt&gt; idiom provides. Given an expression, its resultingvalue is negated by the boolean not operator &lt;tt&gt;!&lt;/tt&gt; and thenthat value is negated to get the resulting boolean value. Let&#39;sbreak that down a little&lt;pre class=&quot;block_code&quot;&gt;  use Data::Dumper;  my $val = &#39;a string which evaluates to true&#39;;  print Dumper  !$val;  print Dumper !!$val;  __output__  $VAR1 = &#39;&#39;;  $VAR1 = &#39;1&#39;;&lt;/pre&gt;So as we can see there the initial negation returns a false value(an empty string &lt;tt&gt;&#39;&#39;&lt;/tt&gt;) to signify the negated truthfulnessof the value. Then secondary double negation returns a true value(the integer &lt;tt&gt;1&lt;/tt&gt;) as the negated form of the false value.&lt;p/&gt;&lt;b&gt;Caveats&lt;/b&gt;&lt;p/&gt;Because it is producing a boolean value from an expression it will not preserve any additional information from the expression. But that&#39;sabout the only caveat, if you could consider it one, and it has the added plus of acting as a boolean internally as explored in[diotalevi]&#39;s [id://367520].&lt;p/&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;p/&gt;Because we are lacking a &lt;tt&gt;&amp;#161;&lt;/tt&gt; operator the &lt;tt&gt;!!expr&lt;/tt&gt;idiom serves to derive a boolean value from an arbitrary expression.
    </description>
</item>

        

<item>
    <title>Getting Matching Items From An Array (Limbic~Region)</title>
    <link>http://prlmnks.org/html/371938.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/371938.html</guid>

    <description>
        &lt;p&gt;&lt;b&gt;Purpose&lt;/b&gt;&lt;br /&gt;On a regular basis, people want to know if a particular thing, we will call it &lt;i&gt;foo&lt;/i&gt;, is present in an array.  The problem with just directing them to FAQ x is that each question usually varies enough to make a single answer unsatisfactory.  The goal of this tutorial is to give enough information so that someone can choose the right solution to the problem.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Is This Tutorial For You?&lt;/b&gt;&lt;br /&gt;A typical mistake is to assume that there is a built-in way of determining presence in an array like there is with a hash.  A red flag should go up if you try using a string for an index as in &lt;tt class=&quot;inline_code&quot;&gt;print &quot;gotcha\n&quot; if $array[&#39;foo&#39;]&lt;/tt&gt;. Perhaps you should be using a hash.  An array gives no &quot;meaning&quot; between the index and the value (though the programmer might as in the case of matrices).  If you are still unsure which to be using, see &lt;i&gt;perldoc perldsc&lt;/i&gt; and &lt;i&gt;perldoc perldata&lt;/i&gt; for more information.&lt;/p&gt;&lt;p&gt;&lt;b&gt;What Will Be Covered&lt;/b&gt;&lt;br /&gt;There are typically 4 answers to the problem of identifying if &lt;i&gt;foo&lt;/i&gt; is present in an array.&lt;ul&gt;&lt;li&gt;Convert the array to a hash&lt;/li&gt;&lt;li&gt;Use the built-in &lt;i&gt;grep&lt;/i&gt;&lt;/li&gt;&lt;li&gt;Use &lt;a href=&quot;/out/cpan/List::Util&quot;&gt;List::Util&lt;/a&gt;&#39;s &lt;i&gt;first&lt;/i&gt;&lt;/li&gt;&lt;li&gt;IYAW (Invent Yet Another Wheel)&lt;/li&gt;&lt;/ul&gt;There are a handful of things to consider and each solution has pros and cons accordingly.  You will need to decide for yourself which is best.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Convert The Array To A Hash&lt;/b&gt;&lt;br /&gt;Depending on your requirements, this can be a very attractive solution (&lt;tt class=&quot;inline_code&quot;&gt;print &quot;It&#39;s in there\n&quot; if exists $sauce{spaghetti}&lt;/tt&gt;).  There is a list of things to consider:&lt;ul&gt;&lt;li&gt;How many items do you need to check?&lt;/li&gt;If you are only checking a single item, this is probably not the best solution.&lt;li&gt;Will the array change between checks?&lt;/li&gt;If you need to rebuild the hash each time you check because you are not sure if the array has changed, this is probably not the best solution.&lt;li&gt;Do you need something other than an exact match?&lt;/li&gt;Using a hash is a bad idea for non exact matches.  The one noteable exception is perhaps case insensitivity.  You can force the keys to a certain case during creation and &lt;i&gt;foo&lt;/i&gt; to the same case when searching.  Even then, it is questionable with regards to this being the best solution.&lt;li&gt;How big is the array?&lt;/li&gt;Duplicating data structures for the convenience of searching can get quite expensive with regards to memory consumption.  You will need to determine how large a footprint is acceptable to you.&lt;li&gt;Do you need to know if there is more than one match?&lt;/li&gt;Remember that hash keys must be unique so using a hash when there is a possibility of duplicates is a bad idea &lt;b&gt;if&lt;/b&gt; you need to know how many times &lt;i&gt;foo&lt;/i&gt; is present in the array.&lt;li&gt;Do you need to know &lt;i&gt;foo&lt;/i&gt;&#39;s index?&lt;/li&gt;Typically for memory reasons, you would build your hash like:&lt;pre class=&quot;block_code&quot;&gt;my %lookup = map { $_ =&gt; undef } @array;print &quot;There it is\n&quot; if exists $lookup{foo};&lt;/pre&gt;But if you have given some meaning to the relationship to the index and the value (or perhaps you want to use &lt;i&gt;splice&lt;/i&gt; to remove it), then you should consider using the following instead:&lt;pre class=&quot;block_code&quot;&gt;my %lookup = map { $array[$_] =&gt; $_ } 0 .. $#array;my $index = $lookup{foo};&lt;/pre&gt;&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;Use The Built-In &lt;i&gt;grep&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;It is fast and powerful and deserves careful consideration:  &lt;ul&gt;&lt;li&gt;How many items do you need to check?&lt;/li&gt;If you are checking many items, this is probably not the best solution because it goes through the entire list even if the match is found the first time.  Keep in mind that &lt;i&gt;many&lt;/i&gt; is subjective and since it has been optimized for efficiency, it still may be acceptable.&lt;li&gt;Will the array change between checks?&lt;/li&gt;You might want to use &lt;i&gt;grep&lt;/i&gt; if the answer is yes or you are unsure since it is &lt;b&gt;not&lt;/b&gt; checking against a copy that might be stale.&lt;li&gt;Do you need something other than an exact match?&lt;/li&gt;You might want to use &lt;i&gt;grep&lt;/i&gt; if the answer is yes or you are unsure.  Since &lt;i&gt;grep&lt;/i&gt; can accept a block, you can easily do a case insensitive search (&lt;tt class=&quot;inline_code&quot;&gt;grep { $_ =~ /^foo$/i } @array&lt;/tt&gt;)&lt;li&gt;How big is the array?&lt;/li&gt;If the array is very large, you may want to consider something other than &lt;i&gt;grep&lt;/i&gt;.  Of course &lt;i&gt;very large&lt;/i&gt; is subjective.  If you are not going to be checking numerous items and you can afford to wait a few extra seconds, &lt;i&gt;grep&lt;/i&gt; might be the perfect choice.&lt;li&gt;Do you need to know if there is more than one match?&lt;/li&gt;Since &lt;i&gt;grep&lt;/i&gt; goes through the entire list, it is an ideal candidate if the answer to this question is yes.  In list context, &lt;i&gt;grep&lt;/i&gt; will return the list of matching items.  In scalar context - it will return the number of matching items.&lt;li&gt;Do you need to know &lt;i&gt;foo&lt;/i&gt;&#39;s index?&lt;/li&gt;Since &lt;i&gt;grep&lt;/i&gt; can take a block, it is very versatile and can easily be adapted to this situation:&lt;pre class=&quot;block_code&quot;&gt;my @indices = grep { $array[$_] eq &#39;foo&#39; } 0 .. $#array;&lt;/pre&gt;&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;Use [cpan://List::Util]&#39;s &lt;i&gt;first&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;It works very much like &lt;i&gt;grep&lt;/i&gt; except it returns on the first match, which depending on your situation can make it a perfect solution.&lt;ul&gt;&lt;li&gt;How many items do you need to check?&lt;/li&gt;At first glance, you might say it does not matter.  One issue is that the &lt;i&gt;first&lt;/i&gt; function is not a compiled built-in like &lt;i&gt;grep&lt;/i&gt;.  A code block is dereferenced and executed for each element in the list until a match is found.  A second issue is that &lt;i&gt;first&lt;/i&gt; does not currently accept a reference as an argument so a list of aliases has to be generated.  Be sure not to worry about premature optimization when the net difference in runtime is a few seconds unless it really matters.&lt;li&gt;Will the array change between checks?&lt;/li&gt;Like &lt;i&gt;grep&lt;/i&gt;, if the answer is yes or you are unsure, you should be considering &lt;i&gt;first&lt;/i&gt; since it is &lt;b&gt;not&lt;/b&gt; checking against a copy that might be stale.&lt;li&gt;Do you need something other than an exact match?&lt;/li&gt;Like &lt;i&gt;grep&lt;/i&gt;, if the answer is yes or you are unsure then &lt;i&gt;first&lt;/i&gt; is a possibility since it takes a block.&lt;li&gt;How big is the array?&lt;/li&gt;Again, you might say it doesn&#39;t matter at first glance since it returns on first match.  The &lt;i&gt;first&lt;/i&gt; function was built to be flexible accepting a code block that has to be dereferenced against each item in the list until a match is found.  If you really need lightening speed then you might want to consider a roll-your-own version that is hard-coded.&lt;li&gt;Do you need to know if there is more than one match?&lt;/li&gt;If the answer is yes, do not choose &lt;i&gt;first&lt;/i&gt; since it is designed to return on first match.&lt;li&gt;Do you need to know &lt;i&gt;foo&lt;/i&gt;&#39;s index?&lt;/li&gt;The &lt;i&gt;first&lt;/i&gt; function can be adapted to handle this situation just like &lt;i&gt;grep&lt;/i&gt;.&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;IYAW (Invent Yet Another Wheel)&lt;/b&gt;&lt;br /&gt;There is rarely a good reason to do this.  Sanity checks such as profiling and benchmarking should be done before you spending valuable time trying to squeeze a couple of seconds  off the runtime.  I can only think of a couple of reasons you might want to do this:&lt;ul&gt;&lt;li&gt;You can&#39;t afford the performance hit of alias construction and repeatedly dereferencing the code block passed to &lt;i&gt;first&lt;/i&gt;&lt;/li&gt;&lt;li&gt;You need to do some transformation before checking but need to keep the original array intact&lt;/li&gt;I freely admit that this falls out of the scope of checking the presence of an item in an array.  By copying the array and then transforming it you have changed the problem.  This does not stop people from asking and so I have included it here for an attempt at completeness.&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; I modified the code snippet in the &quot;Is This Tutorial For You&quot; section to remove &lt;i&gt;exists&lt;/i&gt; per [rob_au]&#39;s suggestion.  It was not necessary to illustrate the point.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Update 2:&lt;/b&gt;  2004-10-02 - [wolv] pointed out to me that the inefficiencies in [cpan://List::Util]&#39;s &lt;i&gt;first&lt;/i&gt; are in the pure perl version.  The XS version is obviously much faster. &lt;/p&gt;
    </description>
</item>

        

<item>
    <title>How will my regular expression match? (hv)</title>
    <link>http://prlmnks.org/html/371722.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/371722.html</guid>

    <description>
        &lt;p&gt;A common source of confusion is the issue of which possible match the regular expression will find in any given instance, and this gives rise to many queries on [Seekers of Perl Wisdom|SOPW] and many different attempts to explain what happens.&lt;/p&gt;&lt;p&gt;A common theme in the explanations is to talk about preferences - the regular expression engine &quot;prefers&quot; longer or shorter matches, or leftmost matches.&lt;/p&gt;&lt;p&gt;The reality is however very simple: the regular expression engine will &lt;b&gt;always return the first match it finds&lt;/b&gt;, and if you understand the &lt;i&gt;order&lt;/i&gt; in which the engine attempts matches, you need never be confused about which match will be found.&lt;/p&gt;&lt;p&gt;A few simple rules (in no particular order) characterise the order in which attempts are made.&lt;/p&gt;&lt;p&gt;&lt;b&gt;1: leftmost character first&lt;/b&gt;&lt;/p&gt;&lt;p&gt;The engine will start trying to match the pattern against the string, starting with the first character of the string. Only if it cannot find any match against the beginning of the string will it start looking for matches starting with the second character of the string, and so on until the string is exhausted.&lt;/p&gt;&lt;p&gt;Example:&lt;pre class=&quot;block_code&quot;&gt;  ($match) = &quot;The longest word&quot; =~ /(\w+)/;  print $match;&lt;/pre&gt;.. will print &quot;The&quot;, since it matches at the beginning of the string. The fact that there is a longer match to find is irrelevant - a match against the beginning of the string succeeded, so this is the match that is returned.&lt;/p&gt;&lt;p&gt;&lt;b&gt;2: leftmost alternation first&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Given a choice of alternates, the leftmost alternate is tried first. If a match is found against the leftmost alternate, the engine will attempt to match the rest of the pattern against the rest of the string; only if no match can be found will the next alternate be tried.&lt;/p&gt;&lt;p&gt;Example:&lt;pre class=&quot;block_code&quot;&gt;  ($match) = &quot;Mrs Smith&quot; =~ /(Mr|Mrs)/;  print $match;&lt;/pre&gt;.. will print &quot;Mr&quot;: the first alternate matched, and thus satisfied the entire pattern, so this is the match returned. The second alternate was never looked at.&lt;/p&gt;&lt;p&gt;&lt;b&gt;3. Maximal (greedy)&lt;/b&gt;&lt;/p&gt;&lt;p&gt;With any normal quantifier (ie any of &lt;tt class=&quot;inline_code&quot;&gt;? * + {1,3}&lt;/tt&gt;), the engine will first try to match the &lt;i&gt;greatest&lt;/i&gt; number of iterations permitted (or the most available if that is fewer than permitted), and try to match the rest of the pattern against the rest of the string. Only if the rest of the pattern fails to match will it try matching one fewer iteration, and repeat until the minimum permitted number is reached.&lt;/p&gt;&lt;p&gt;Example:&lt;pre class=&quot;block_code&quot;&gt;  ($match) = &quot;/foo/bar&quot; =~ m[.*/(.*)];  print $match;&lt;/pre&gt;.. prints &quot;bar&quot;: the engine tries to match the initial &lt;tt class=&quot;inline_code&quot;&gt;.*&lt;/tt&gt; against &quot;/foo/bar&quot;, then &quot;/foo/ba&quot;, then &quot;/foo/b&quot;, then &quot;/foo/&quot;, then &quot;/foo&quot;. At this point the remaining pattern matches, so this is the match returned.&lt;/p&gt;&lt;p&gt;&lt;b&gt;4. Minimal (non-greedy)&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Adding a &#39;?&#39; after a quantifier (ie &lt;tt class=&quot;inline_code&quot;&gt;?? *? +? {1,3}?&lt;/tt&gt;) requests a minimal match, so the order is reversed: the engine first attempts to match the fewest number of iterations permitted and if it can, attempts to match the rest of the pattern against the rest of the string. Only if that fails does it try matching one more iteration, and continues increasing the number of iterations matched until the upper limit is reached.&lt;/p&gt;&lt;p&gt;Example:&lt;pre class=&quot;block_code&quot;&gt;  ($match) = &quot;foo/bar/baz&quot; =~ m[.*?/(.*)];  print $match;&lt;/pre&gt;.. prints &quot;bar/baz&quot;: the engine tries to match the initial &lt;tt class=&quot;inline_code&quot;&gt;.*&lt;/tt&gt; against &quot;&quot;, then &quot;f&quot;, then &quot;fo&quot;, then &quot;foo&quot;. At this point the rest of the pattern matches, so this is the match that is returned.&lt;/p&gt;&lt;p&gt;&lt;b&gt;5. Pattern components: left to right&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Implicit in some of the above examples is that the components of the pattern are matched from left to right. So in the &#39;maximal&#39; example above, the engine decides first (based on the rules above) how it is going to try to match the initial &lt;tt class=&quot;inline_code&quot;&gt;.*&lt;/tt&gt;, and only after that is fixed does it start worrying about the remaining components of the pattern.&lt;/p&gt;&lt;p&gt;&lt;b&gt;6. Nesting&lt;/b&gt;&lt;/p&gt;&lt;p&gt;This is really just more of the &quot;left to right&quot; rule, best explained by example:&lt;pre class=&quot;block_code&quot;&gt;  ($outer, $inner) = &quot;/foo/bar&quot; =~ m[(/(.+))*];  print $inner;&lt;/pre&gt;.. prints &quot;foo/bar&quot;. The engine reaches the outer quantifier, knows it should match it as many times as possible, and attempts to match its innards. The first iteration of the innards reaches the nested quantifier, and tries to match &lt;i&gt;it&lt;/i&gt; as many times as possible, giving &quot;foo/bar&quot;. At this point, the outer quantifier cannot be matched a second time but that&#39;s fine - the pattern has been fully satisfied, and so this match is returned.&lt;/p&gt;&lt;p&gt;That covers most of the standard cases. There are a few other possibilities to consider (eg anchors, &lt;tt class=&quot;inline_code&quot;&gt;pos()&lt;/tt&gt;, and the various zero-width assertions). Also, the optimiser may sometimes cause the engine to skip some steps, but only if it is sure that the actual match found will be the same.&lt;/p&gt;&lt;p&gt;I hope this will help you work out which match your regular expression will find.&lt;/p&gt;&lt;p&gt;Hugo&lt;/p&gt;
    </description>
</item>

        

<item>
    <title>Using select and IO::Select (duff)</title>
    <link>http://prlmnks.org/html/371720.html</link>
    <guid isPermaLink="true">http://prlmnks.org/html/371720.html</guid>

    <description>
        Here&#39;s a tutorial I started on using [doc://select] (primarily because I saw a [id://370963|query] from [tachyon] on it and I figured it was a good thing to do).  This is just a first cut, so be kind and send me your comments. :-)&lt;p&gt;Also, is there a way for perlmonks.org to automagically handle POD format?&lt;pre class=&quot;block_code&quot;&gt;=head1 NAMEperlselecttut - a tutorial on using select() and IO::Select=head1 DESCRIPTIONThis document attempts to explain how to use the 4-arg version ofC&lt;select()&gt; and the module C&lt;IO::Select&gt; so that they are easier tounderstand.  If anything is unclear, the authorof this document would appreciate hearing about it.=head2 What are C&lt;select()&gt;/C&lt;IO::Select&gt; and why would you use them?Without going into too much detail (none at all in fact) C&lt;select()&gt; andC&lt;IO::Select&gt; are useful for when you want to &quot;watch&quot; severalfilehandles at once to see if they are ready for reading or writing orif any of them have an exception condition. Now, when I say&quot;filehandles&quot; I really mean anything that can be read or written to asif it were a file: sockets, serial devices, pipes, fifos, etc. Anexample application that would use C&lt;select&gt; is a chat server. Eachclient that is connected to the server occupies it&#39;s own socket(filehandle), so the server would use C&lt;select&gt; to see what each clientsays having to wait on any particular client.Caveat lector!  This document is mostly written from a unix-centricpoint of view, but similar ideas apply on other operating systems.=head2 All about C&lt;select()&gt;Here&#39;s the canonical C&lt;select()&gt; example that you will find in thedocumentation:($nfound,$timeleft) =   select($rout=$rin, $wout=$win, $eout=$ein, $timeout);But what does it all mean?  Why the assignments?  Why those particularvariable names?  The first 3 arguments to C&lt;select()&gt; tell it which filehandles to watchfor reading, writing, and exceptions respectively (thus the leading r,w, and e on each variable).  These arguments are each a specialbitvector where each &quot;on&quot; bit corresponds to the filedescriptor numberof the filehandle that is being watched.  The fourth argument toC&lt;select()&gt; is how long to watch the filehandles before giving up.  TheC&lt;select()&gt; call returns a count of how many filehandles have triggeredone of the reading/writing/exception conditions (C&lt;$nfound&gt;) and theamount of time left in the timeout specified (C&lt;$timeleft&gt;).=head3 What are filedescriptors?Each time you open a file, the operating system makes an entry insomething called a file descriptor table so that it can keep track ofthe file (things like the current position, whether or not it&#39;sbuffered, the contents of the buffer, etc.) By default the entry atindex 0 is STDIN, at index 1 is STDOUT and STDERR is at index 2. Theindex into the filedescriptor table is called the file descriptor numberor L&lt;fileno&gt; for short. It&#39;s these indexes that are used as offsets intothe bitvector to identify to C&lt;select()&gt; which filehandles you wish towatch.=head3 Using C&lt;vec()&gt; to build bitvectorsA bitvector is an odd thing for perl because it&#39;s so low level. Havingto fiddle with bitvectors shows how close C&lt;select()&gt; is to its C heritage.But luckily perl remembers its heritage through a function calledC&lt;vec()&gt;.   To create a bitvector for use with C&lt;select()&gt; with theproper bit turned on for STDIN you would write:vec($vector,fileno(STDIN),1) = 1;C&lt;fileno()&gt; is a routine that returns the index into thefiledescriptor table for a given filehandle (aka. the fileno).  Sincewe know STDIN is at index 0, we could have writtenvec($vector,0,1) = 1;But that would be I&lt;extremely&gt; unportable. If, for some reason, wehappened to run on a system that used 0 for some other filehandle outprogram wouldn&#39;t work as expected. This I&lt;could&gt; happen if we closedSTDIN, then opened another file. The operating system may use the firstavailable free filedescriptor when you open a new file and since weclosed STDIN, descriptor 0 would be free.Anyway, the call to C&lt;vec()&gt; means: treat $vector is a bitvector andaccess the bits starting at the bit position corresponding to the theindex into the filedescriptor table for the filehandle STDIN for 1 bitand assign that bit the value 1. So, to watch several filehandles youwould do this:vec($vector,fileno(FOO),1) = 1;vec($vector,fileno(BAR),1) = 1;vec($vector,fileno(BAZ),1) = 1;and then use C&lt;$vector&gt; in the call to C&lt;select()&gt; to watch the FOO,BAR, and BAX filehandles.See C&lt;perldoc -f vec&gt; for more information on C&lt;vec()&gt;=head3 Why are we doing assignments in the C&lt;select()&gt; call?The reason you typically see assignments in the first three positions isthat C&lt;select()&gt; modifies its first 3 arguments to tell you I&lt;which&gt;filehandles have data ready for reading or writing or exceptions and youusually want to continually watch the same filehandles over and overagain. Since the followingselect($rout=$rin, $wout=$win, $eout=$ein, $timeout);functions the same as $rout = $rin; $wout = $win; $eout = $ein;select($rout, $wout, $eout, $timeout);The assignments allow $rin,$win, and $ein to keep their original valuesso that you can call it in a loop without having to continually buildthe bit vectors.  Contrast these two functionally equivalent snippets:# Example 1, the usual idiomvec($rin,fileno(FOO),1) = 1;vec($rin,fileno(BAR),1) = 1;vec($rin,fileno(BAZ),1) = 1;while (1) {   ($found) = select($rout=$rin,undef,undef,$timeout);   next unless $found;   # Check $rout to see which handles are ready for reading}# Example 2, building the vectors each timewhile (1) {   vec($rinout,fileno(FOO),1) = 1;   vec($rinout,fileno(BAR),1) = 1;   vec($rinout,fileno(BAZ),1) = 1;   ($found) = select($rinout,undef,undef,$timeout);   next unless $found;   # Check $rinout to see which handles are ready for reading}Oh, btw, you&#39;ll notice that I used C&lt;undef&gt; for the second and thirdargument to C&lt;select()&gt;. If you don&#39;t care to check any filehandlesfor reading, writing, or exceptions you can pass C&lt;undef&gt; in therespective position and C&lt;select()&gt; won&#39;t bother paying attention tothat condition.  You can also pass c&lt;undef&gt; for the timeout andC&lt;select()&gt; will wait forever for a filehandle to trigger theappropriate condition.  =head3 Checking which filehandles are readyAfter C&lt;select()&gt; returns, the three bitvectors will have changed toreflect the actual filehandles that triggered the particular conditionyou were waiting for.  One way to check which filehandle is ready isto just use C&lt;vec()&gt; again to see if the particular bit is 1.  Forexample:vec($rin,fileno(FH1),1) = 1;vec($rin,fileno(FH2),1) = 1;vec($rin,fileno(FH3),1) = 1;while (1) {   ($found) = select($rout=$rin,undef,undef,$timeout);   next unless $found;   if (vec($rout,fileno(FH1),1) == 1) {      # There is data waiting to be read on FH1   }   if (vec($rout,fileno(FH2),1) == 1) {      # There is data waiting to be read on FH2   }   # and so on ...}Another method would be to use C&lt;select()&gt; again. vec($fh1,fileno(FH1),1) = 1;vec($fh2,fileno(FH2),1) = 1;vec($fh3,fileno(FH3),1) = 1;$rin = $fh1 | $fh2 | $fh3;while (1) {   ($found) = select($rout=$rin,undef,undef,$timeout);   next unless $found;   if (select($fh1,undef,undef,$timeout)) {      # There is data waiting to be read on FH1   }   if (select($fh2,undef,undef,$timeout)) {      # There is data waiting to be read on FH2   }   # and so on ...}By building individual bitvectors for each filehandle and then combiningthem together using a bit-wise OR, we can check whether I&lt;any&gt; of thefilehandles are ready with the combined bitvector or whether anindividual filahandle is ready with the individual bitvectors usingC&lt;select()&gt;.Note that several filehandles may be ready at once, so it would beprudent to service as many of the filehandles that you can beforecalling C&lt;select()&gt; again.=head3 I know which filehandles are ready.  Now what?After you have setup C&lt;select()&gt; and determined which filehandles Areready, you&#39;ll want to read from those filehandles that are ready forreading and write to those filehandles that are ready for writing and dowhatever is necessary to those filehandles that have an exceptioncondition. [ To be honest, I&#39;ve never used the ability to check forexception conditions on filehandles and I have little understanding ofwhat it may be for. The only reference I have handy at the moment,Stevens&#39; U&lt;Advanced Programming in the Unix Environment&gt;, says &quot;... anexception condition corresponds to (a) the arrival of out-of-band dataon a network connection, or (b) certain conditions occuring on a psuedoterminal that has been placed into packet mode&quot; ] But you must becareful how you read or write data to the filehandle. Buffered I/O likeC&lt;readline()&gt; (aka, the diamond operator or &lt;&gt;) or C&lt;read()&gt;, won&#39;t workquite right, so you need to use C&lt;sysread()&gt; and C&lt;syswrite()&gt; toread/write from/to the appropriate filehandles.=head2 IO::SelectAs you can tell by now, C&lt;select()&gt; isn&#39;t the friendliest of routinesto use.  Luckily you have another option: C&lt;IO::Select&gt;.  C&lt;IO::Select&gt;is an object oriented interface that sits on top of the basicC&lt;select()&gt; routine such that you never have to see bitvectors andstrange assignments.  You deal only with C&lt;IO::Select&gt; objects and thefilehandles themselves.  Here&#39;s a simple example:use IO::Select;my $sel = IO::Select=&gt;new;$sel-&gt;add(\*FOO);$sel-&gt;add(\*BAR);$sel-&gt;add(\*BAZ);if (@fh = $sel-&gt;can_read($timeout)) {   # Each filehandle in @fh is ready to be read from}The basic usage is simple:  you create a IO::Select object (possiblyinitializing it with filehandles), then add new file handles to theobject using the C&lt;add()&gt; method, and when you&#39;re ready to &quot;watch&quot; thefilehandles you call one of the C&lt;can_read()&gt;, C&lt;can_write()&gt;, orC&lt;has_exception()&gt; methods on the object.  Each of these methodsreturns an array of filehandles such that you can read/write from/tothem.=head1 AUTHOR Jonathan Scott Duff duff@cpan.org&lt;/pre&gt;
    </description>
</item>

    </channel>
</rss>
