Just somewhere to keep my notes while I'm playing.

Tuesday, April 9, 2013

Simple Perl

Perl is a highly complicated language, but it is possible to do some useful things using some pretty simple code. Here are a few examples.

Example 1
Here is a simple example of a program that reads a file and prints it out. I'm sure that it could be written with fewer lines of code, but this has the advantage of being a framework for any program you might need to write.
$ cat testfile
micky mouse
mini mouse
daffy duck

tjinkers@JINKERSON-PC ~/example
$ cat ./filelister.pl
#!/usr/bin/perl
use File::stat;
my $IFILE = $ARGV[0];
die "Unable to open input file\n" unless (open $inputfile, $IFILE);
while (<$inputfile>) {
        chomp;
        print $_ . "\n";
}
close  $inputfile;

tjinkers@JINKERSON-PC ~/example
$  ./filelister.pl testfile
micky mouse
mini mouse
daffy duck

tjinkers@JINKERSON-PC
~/example
Things to note:
  • $ARGV[0] is the first command line argument
  • 'die ... unless' - most programming languages put the condition before the action, but Perl is not fussy, and so here we tell the program to 'die' (end with an error condition) unless it is able to open its input file.
  • 'chomp' - if the final character of a string is a carriage return / line feed, remove it. Like so many Perl instructions, if you don't specify the variable, it uses the result of the previous operation, stored in $_
  • 'print $_ . "\n"' - print the result of the previous operation to stdout, concatenated with a new line character.
Example 2
Here is a  re-write of the above example, this time using a subroutine.
#!/usr/bin/perl
use strict;
use warnings;
sub processfile {
   die "Unable to open input file\n" unless (open my $inputfile, $_[0]);
   while (<$inputfile>) {
        chomp;
        print $_ . "\n";
   }
   close  $inputfile;
}
main {
   my $IFILE = $ARGV[0];
   processfile($IFILE);
   exit 0;
}
Things to note:

  • use strict; forces you to get the syntax write - always good practice!
  • We either need to declare the subroutine ahead of the main section, or include a dummy declaration above it.
Example 3
Here is another example, this time using a subroutine that returns a value, otherwise known as a function.
#!/usr/bin/perl
use strict;
use warnings;
use Scalar::Util qw(looks_like_number);
sub addthem {
   my $var=0;
   my $sum=0;
   foreach $var ( @_ ) {
     print $var . "\n";
     $sum=$sum+$var if (looks_like_number($var));
   }
   return $sum;
}
main {
   print addthem(@ARGV) . "\n";
   exit 0;
}


 Things to note:

  • The subroutine is called within the print statement.
  • The variable passed to the subroutine is an array of values which we rattle through, adding them up.
  • We are using the Scalar::Util utility to determine if the value passed is numeric. This utility contains a number of useful functions that are not quite popular enough to include in the main language definition.

Example 4
Here is a more complex example. The request was to write a piece of code that would read through a file. If it found 2 predetermined lines next to each other, the code had to insert the contents of a file beneath the second line. If the lines were not next to each other in sequence, they were to be ignored.

#!/usr/bin/perl
use File::stat;
use IO::File;
use warnings;
use strict;

die "Could not open stdin\n" unless ( open my $stdin, "< &STDIN");
my $trigger = "safety";
while (<$stdin>) {
        chomp;
        my $line = $_;
        print $line . "\n";
        if ( $line eq "line 2" ) {
                $trigger = "primed";
        } else {
                if ( $line eq "line 3" && $trigger eq "primed" ) {
                        ## print "Fire!\n";
                        die "Could not open include file\n" unless ( open my $ifile, "./insertfile.txt");
                        while (<$ifile>) {
                                chomp;
                                print $_ . "\n";
                        }
                        close $ifile;
                }
                $trigger = "safety";
        }
} 

No comments: