Fundamentals of Perl
Fundamentals of Perl
Fundamentals of Perl
Gabor Szabo
Fundamentals of Perl
by Gabor Szabo
1.11 Edition
Published Sun May 27 23:22:58 2007
Copyright © 2001, 2002, 2003, 2004, 2005, 2006, 2007 PTI Ltd. Perl Training Israelhttp://www.pti.co.il/
Table of Contents
1. About Perl Training Israel ....................................................................................................................1
2. Introduction............................................................................................................................................2
2.1. Self Introduction - Who am I ? ...................................................................................................2
2.2. Self Introduction - Who are you ?...............................................................................................2
3. Preface ....................................................................................................................................................3
3.1. Content ........................................................................................................................................3
4. First steps................................................................................................................................................4
4.1. Installation...................................................................................................................................4
4.2. Editors, IDEs ...............................................................................................................................4
4.3. Environment ................................................................................................................................4
4.4. Safety net.....................................................................................................................................5
4.5. Comments ...................................................................................................................................5
4.6. Perl documentation .....................................................................................................................6
4.7. POD - Plain Old Documentation ................................................................................................6
4.8. Exercise: Hello world..................................................................................................................7
5. Scalars.....................................................................................................................................................9
5.1. Numbers - integers, real or floating-point ...................................................................................9
5.2. Scalar variables (use my) ............................................................................................................9
5.3. Greeting with a name, Variable interpolation ...........................................................................10
5.4. User Input..................................................................................................................................10
5.5. chomp........................................................................................................................................10
5.6. Numerical Operators .................................................................................................................11
5.7. String Operators ........................................................................................................................12
5.8. Dividing two numbers given by the user...................................................................................12
5.9. Fixing the problem: Conditional statements: if.........................................................................13
5.10. Syntax of if statement .............................................................................................................14
5.11. Comparison operators .............................................................................................................14
5.12. String - Number conversion ....................................................................................................15
5.13. Compare values .......................................................................................................................15
5.14. Compare values - examples.....................................................................................................16
5.15. Boolean expressions (logical operators) .................................................................................17
5.16. TRUE and FALSE...................................................................................................................17
5.17. Your Salary is in Danger - Short-Circuit.................................................................................18
5.18. String functions .......................................................................................................................18
5.19. String functions .......................................................................................................................19
5.20. Strings - Double quoted ..........................................................................................................19
5.21. Strings - Single quoted ............................................................................................................20
5.22. Scope of variables ...................................................................................................................20
5.23. Random numbers ....................................................................................................................21
5.24. Exercises: Simple Calcualtor ..................................................................................................21
5.25. Number Guessing game ..........................................................................................................21
5.26. Solution: Simple Calulator......................................................................................................22
5.27. Solution: Simple Calulator (using eval) ..................................................................................22
iii
6. Files .......................................................................................................................................................24
6.1. die, warn, exit ............................................................................................................................24
6.2. Opening file for reading ............................................................................................................24
6.3. Opening a file ............................................................................................................................24
6.4. Opening a file - error handling ..................................................................................................24
6.5. Opening a missing file...............................................................................................................25
6.6. Read one line from a file ...........................................................................................................25
6.7. Process an entire file line by line (while, cat) ...........................................................................26
6.8. Write to a file.............................................................................................................................26
6.9. Sum of numbers in a file ...........................................................................................................27
6.10. Analyze the Apache log file ....................................................................................................27
6.11. Open files in the old way.........................................................................................................28
6.12. Exercise: Add more statistics ..................................................................................................29
6.13. Exercise: Write report to file ...................................................................................................29
6.14. Exercise: Analyze Apache - number of successful hits ..........................................................29
6.15. Solution: Add more statistics ..................................................................................................29
6.16. Solution: Analyze Apache - number of successful hits ..........................................................30
6.17. Solution: Write report to file ...................................................................................................31
7. Lists and Arrays...................................................................................................................................33
7.1. List Literals, list ranges .............................................................................................................33
7.2. List Assignment ........................................................................................................................33
7.3. loop over elements of list with foreach .....................................................................................33
7.4. Create an Array, loop over with foreach ...................................................................................34
7.5. Array Assignment .....................................................................................................................34
7.6. foreach loop on numbers...........................................................................................................34
7.7. Array index (menu) ...................................................................................................................35
7.8. Command line parameters ........................................................................................................35
7.9. Process command line parameters, use modules ......................................................................36
7.10. Module documentation ...........................................................................................................37
7.11. process csv file ........................................................................................................................37
7.12. process csv file (short version)................................................................................................38
7.13. process csv file using Text::CSV_XS .....................................................................................38
7.14. Join ..........................................................................................................................................39
7.15. Exercise: improve the color selector .......................................................................................39
7.16. Improve the Number Guessing game from the earlier chapter ...............................................39
7.17. Solution: improved color selector ...........................................................................................40
8. Advanced Arrays .................................................................................................................................42
8.1. The year 19100..........................................................................................................................42
8.2. SCALAR and LIST Context .....................................................................................................42
8.3. Context Sensitivity ....................................................................................................................43
8.4. Filehandle in scalar and list context ..........................................................................................43
8.5. slurp mode.................................................................................................................................44
8.6. File::Slurp..................................................................................................................................44
8.7. pop, push ...................................................................................................................................45
8.8. stack (pop, push) .......................................................................................................................45
8.9. shift, unshift ..............................................................................................................................46
8.10. queue (shift, push)...................................................................................................................47
ix
Chapter 1. About Perl Training Israel
PTI has been providing training and development services since 2000. Our courses include the following:
Perl Courses
• Fundamentals of Perl
• References, Modules and Objects (Advanced)
• Web Application Development with Perl (Advanced)
• Debugging Perl Scripts and Applications (Advanced)
• Perl Quick Start (Beginner)
• QA Automation using Perl (Advanced)
• Perl for QA Professionals (Beginner)
Non-Perl Courses
1
Chapter 2. Introduction
2
Chapter 3. Preface
3.1. Content
• Introduction to writing Perl
• Many code snippets that can be used as base or as example
• Introduction to basic syntax
• Many examples explained
• Many examples where not all the syntax is explained
3
Chapter 4. First steps
4.1. Installation
• Emacs http://www.gnu.org/software/emacs/
• vi, vim, gvim http://www.vim.org/
• Crimson Editor http://www.crimsoneditor.com/
• Notepad++ http://notepad-plus.sourceforge.net/
• Textpad http://www.textpad.com/
• Multi-Edit http://www.multiedit.com/
• Komodo of ActiveState http://www.activestate.com/
• Eclipse http://www.eclipse.org/
• SlickEdit http://www.slickedit.com/
4.3. Environment
On the command line one can type:
perl -v
perl -V
4
Chapter 4. First steps
#!/usr/bin/perl
use strict;
use warnings;
On unix you can also make it executable: chmod u+x hello_world.pl and then run like: ./hello_world.pl
A couple of notes
You should always use them as they are a safety net helping reduce mistakes.
It is usually very hard to add this safety net after you already have some code.
use diagnostics;
Why are use warnings and use strict so important even in small (< 100 lines) scripts ?
4.5. Comments
# Comments for other developers
perldoc -q sort
perldoc perlrun
perldoc strict
perldoc warnings
An index: http://www.szabgab.com/articles/perlindex.html
Web based: http://perldoc.perl.org/
#!/usr/bin/perl
use strict;
use warnings;
=head2 Subtitle
=item * element
more text
=over 4
=item *
Issue
=item *
Other issue
=back
=cut
perl examples/intro/documentation.pl
perldoc examples/intro/documentation.pl
• Make sure you have access to the right version of Perl (5.8.x)
• Check you can read the documentation.
• Check if you have a good editor with syntax highlighting
• Write a simple script that prints Hello world
• Add comments to your code
• Add user documentation to your code
26
1_234_567_890
integer (hex/oct/binary)
real or floating-point
3.5e+3 # 3500
$this_is_a_long_scalar_variable
$ThisIsAlsoGoodButWeUseItLessInPerl
$h
$H # $h and $H are two different variables
#!/usr/bin/perl
use strict;
use warnings;
9
Chapter 5. Scalars
A scalar can hold either string or numerical value. They can be changed any
time. If a value was not given it holds the special value ’undef’.
#!/usr/bin/perl
use strict;
use warnings;
my $name = "Foo";
print "Hello ", $name, " - how are you ?\n";
#!/usr/bin/perl
use strict;
use warnings;
$ perl examples/read_from_stdin.pl
Enter your name, please: Foo
Hello Foo
, how are you ?
5.5. chomp
Example 5-4. examples/scalars/read_from_stdin_chomp.pl
#!/usr/bin/perl
use strict;
use warnings;
chomp will remove the new line "\n" character from the end of the string if there was one.
#!/usr/bin/perl
use strict;
use warnings;
my $x = 3;
my $y = 11;
my $z = $x + $y;
print "$z\n"; # 14
$z = $x * $y;
print "$z\n"; # 33
print $y / $x, "\n"; # 3.66666666666667
$z = $y % $x; # (modulus)
print "$z\n"; # 2
$z = 23 ** 2; # exponentiation
print "$z\n"; # 529
#!/usr/bin/perl
use strict;
use warnings;
my $x = 7;
$x = 7;
$y = ++$x;
print "y = $y, x = $x\n"; # y = 8, x = 8
#!/usr/bin/perl
use strict;
use warnings;
my $x = "Hello";
my $y = "World";
#!/usr/bin/perl
use strict;
use warnings;
my $z = $x / $y;
print "The result is $z\n";
$ perl examples/divide.pl
First number: 27
Second number: 3
9
$ perl examples/divide.pl
First number: 27
Second number: 0
Illegal division by zero at examples/divide.pl line 9, <STDIN> line 2.
#!/usr/bin/perl
use strict;
use warnings;
if ($y == 0) {
print "Cannot divide by zero\n";
} else {
my $z = $x / $y;
print "The result is $z\n";
}
if (COND) {
STATEMENTs;
}
if (COND) {
STATEMENTs;
} else {
STATEMENTs;
}
if (COND_1) {
A_STATEMENTs;
} else {
if (COND_2) {
B_STATEMENTs;
} else {
if (COND_3) {
C_STATEMENTs;
} else {
D_STATEMENTs;
}
}
}
if (COND_1) {
A_STATEMENTs;
} elsif (COND_2) {
B_STATEMENTs;
} elsif (COND_3) {
C_STATEMENTs;
} else {
D_STATEMENTs;
}
#!/usr/bin/perl
use strict;
use warnings;
print "3x" + 0, "\n"; # warning: Argument "3x" isn’t numeric in addition (+)
print "3\n" + 0, "\n";
print "3x7" + 0, "\n"; # warning: Argument "3x7" isn’t numeric in addition (+)
print "" + 0, "\n"; # warning: Argument "" isn’t numeric in addition (+)
print "z" + 0, "\n"; # warning: Argument "z" isn’t numeric in addition (+)
print "z7" + 0, "\n"; # warning: Argument "z7" isn’t numeric in addition (+)
#!/usr/bin/perl
use strict;
use warnings;
my $first = <STDIN>;
chomp $first;
my $other = <STDIN>;
chomp $other;
if ($first == $other) {
print "The two numbers are the same\n";
} else {
print "The two numbers are NOT the same\n";
}
if ($first eq $other) {
print "The two strings are the same\n";
} else {
print "The two strings are NOT the same\n";
}
if ($first gt $other) {
print "First is a BIGGER string\n";
} else {
print "First is a smaller string\n";
}
Expression Value
"12.0" == 12 TRUE
"12.0" eq 12 FALSE
2<3 TRUE
2 lt 3 TRUE
12 > 3 TRUE
12 gt 3 FALSE !
"" == "hello" TRUE ! (Warning)
"" eq "hello" FALSE
"hello" == "world" TRUE ! (Warning)
"hello" eq "world" FALSE
#!/usr/bin/perl
use strict;
use warnings;
my $input = <STDIN>;
chomp $input;
if ($input == "") { # wrong! use eq
# empty string
}
and &&
or ||
not !
if (COND or COND) {
}
if (not COND) {
}
See also perldoc perlop for precedence and associativity tables and/or use () to define the order of
evaluation.
undef
""
0 0.0 00000 0e+10
"0"
"0\n"
if ($z) {
# $z is true
}
if (defined $x) {
# $x is defined (not undef)
}
#!/usr/bin/perl
use strict;
use warnings;
print "\n";
#!/usr/bin/perl
use strict;
use warnings;
my $name = "Foo";
print "Hello $name, how are you?"; # Hello Foo, how are you?
There are only two special characters in this kind of string the ’
and the \ at the end of the string
#!/usr/bin/perl
use strict;
use warnings;
my $fname = "Foo";
my $lname = "Bar";
print "$fname\n"; # Foo
print "$lname\n"; # Bar
{
my $email = ’foo@bar.com’;
print "$email\n"; # foo@bar.com
print "$fname\n"; # Foo
print "$lname\n"; # Bar
my $lname = "Moo";
print "$lname\n"; # Moo
}
# $email does not exists
print "$fname\n"; # Foo
print "$lname\n"; # Bar
#!/usr/bin/perl
use strict;
use warnings;
#!/usr/bin/perl
use strict;
use warnings;
print "Type in 2 numbers and an operator and I’ll print the results\n\n";
my $result;
if ($oper eq "+") { $result = $first + $other; }
if ($oper eq "-") { $result = $first - $other; }
if ($oper eq "*") { $result = $first * $other; }
if ($oper eq "/") {
if ($other == 0) {
print "\nCannot divide by 0\n";
$result = "ERROR";
} else {
$result = $first / $other;
}
}
#!/usr/bin/perl
use strict;
use warnings;
print "Type in 2 numbers and an operator and I’ll print the results\n\n";
If no \n at the end of the string both warn and die add the
name of file and line number and possibly the chunk of the input.
Before you can read from a file you have to ask the Operating System to "open"
it for you. When opening a file you provide a variable that will become your
handle to the opened file. It is called a filehandle.
my $filename = "input.txt";
open(my $fh, "<", $filename);
close $fh;
24
Chapter 6. Files
#!/usr/bin/perl
use strict;
use warnings;
my $filename = "input.txt";
if (open my $in, "<", $filename) {
# do your thing here
# no need to explicitly close the file
} else {
warn "Could not open file ’$filename’. $!";
}
# here the $in filehandle is not accessible anymore
A more Perlish way to open a file and exit with error message if you could not open the file:
#!/usr/bin/perl
use strict;
use warnings;
my $filename = "input.txt";
open(my $fh, "<", $filename) or die "Could not open file ’$filename’. $!";
# do your thing here
close $fh;
#!/usr/bin/perl
use strict;
use warnings;
#!/usr/bin/perl
use strict;
use warnings;
} else {
warn "Could not open file ’$filename’: $!";
}
#!/usr/bin/perl
use strict;
use warnings;
my $filename = "input.txt";
open(my $fh, "<", $filename) or die "Could not open ’$filename’\n";
while (my $line = <$fh>) {
print $line;
}
#!/usr/bin/perl
use strict;
use warnings;
my $filename = "report.txt";
open my $fh, ’>’, $filename or die "Could not open file ’$filename’ $!";
#!/usr/bin/perl
use strict;
use warnings;
# given a file with a number on each row, print the sum of the numbers
my $sum = 0;
my $filename = "numbers.txt";
open(my $fh, "<", $filename) or die "Could not open ’$filename’\n";
while (my $line = <$fh>) {
$sum += $line;
}
print "The total value is $sum\n";
127.0.0.1 - - [10/Apr/2007:10:39:11 +0300] "GET / HTTP/1.1" 500 606 "-" "Mozilla/5.0 (X11; U
127.0.0.1 - - [10/Apr/2007:10:39:11 +0300] "GET /favicon.ico HTTP/1.1" 200 766 "-" "Mozilla/
139.12.0.2 - - [10/Apr/2007:10:40:54 +0300] "GET / HTTP/1.1" 500 612 "-" "Mozilla/5.0 (X11;
139.12.0.2 - - [10/Apr/2007:10:40:54 +0300] "GET /favicon.ico HTTP/1.1" 200 766 "-" "Mozilla
127.0.0.1 - - [10/Apr/2007:10:53:10 +0300] "GET / HTTP/1.1" 500 612 "-" "Mozilla/5.0 (X11; U
127.0.0.1 - - [10/Apr/2007:10:54:08 +0300] "GET / HTTP/1.0" 200 3700 "-" "Mozilla/5.0 (X11;
127.0.0.1 - - [10/Apr/2007:10:54:08 +0300] "GET /style.css HTTP/1.1" 200 614 "http://pti.loc
127.0.0.1 - - [10/Apr/2007:10:54:08 +0300] "GET /img/pti-round.jpg HTTP/1.1" 200 17524 "http
127.0.0.1 - - [10/Apr/2007:10:54:21 +0300] "GET /unix_sysadmin.html HTTP/1.1" 200 3880 "http
217.0.22.3 - - [10/Apr/2007:10:54:51 +0300] "GET / HTTP/1.1" 200 34 "-" "Mozilla/5.0 (X11; U
217.0.22.3 - - [10/Apr/2007:10:54:51 +0300] "GET /favicon.ico HTTP/1.1" 200 11514 "-" "Mozil
217.0.22.3 - - [10/Apr/2007:10:54:53 +0300] "GET /cgi/pti.pl HTTP/1.1" 500 617 "http://conta
127.0.0.1 - - [10/Apr/2007:10:54:08 +0300] "GET / HTTP/0.9" 200 3700 "-" "Mozilla/5.0 (X11;
217.0.22.3 - - [10/Apr/2007:10:58:27 +0300] "GET / HTTP/1.1" 200 3700 "-" "Mozilla/5.0 (X11;
217.0.22.3 - - [10/Apr/2007:10:58:34 +0300] "GET /unix_sysadmin.html HTTP/1.1" 200 3880 "htt
217.0.22.3 - - [10/Apr/2007:10:58:45 +0300] "GET /talks/Fundamentals/read-excel-file.html HT
#!/usr/bin/perl
use strict;
use warnings;
my $file = "examples/files/apache_access.log";
open my $fh, ’<’, $file or die "Could not open ’$file’: $!";
my $good;
my $bad;
while (my $line = <$fh>) {
chomp $line;
my $length = index ($line, " ");
my $ip = substr($line, 0, $length);
if ($ip eq "127.0.0.1") {
$good++;
} else {
$bad++;
}
}
#!/usr/bin/perl
use strict;
use warnings;
my $filename = "data.txt";
open(FH, $filename);
my $line = <FH>;
close FH;
open(FH, ">$filename");
print FH "data";
close FH;
Security problems.
minimum
maximum
average
median and standard deviation are probably too difficult for now.
minimum: -17
maximum: 98
total: 126
count: 6
average: 21
Please create a report showing how many of the hits were successful (200)
and how many were something else.
#!/usr/bin/perl
use strict;
use warnings;
my $total = 0;
my $count = 0;
my $min;
my $max;
my $filename = "numbers.txt";
open(my $fh, "<", $filename) or die "Could not open ’$filename’\n";
while (my $line = <$fh>) {
chomp $line;
$total += $line;
if (not $count) {
$min = $line;
$max = $line;
}
$count++;
#!/usr/bin/perl
use strict;
use warnings;
my $file = "examples/files/apache_access.log";
open my $fh, ’<’, $file or die "Could not open ’$file’: $!";
my $good = 0;
my $bad = 0;
my $ugly = 0;
while (my $line = <$fh>) {
chomp $line;
my $request = q( HTTP/1.1" );
my $start_request = index ($line, $request);
my $result;
if ($start_request >= 0) {
my $end_request = index($line, " ", $start_request + length($request));
$result = substr($line, $start_request + length($request), $end_request-$start_reque
#print "$start_request, $end_request ’$result’\n";
} else {
my $request = q( HTTP/1.0" );
my $start_request = index ($line, $request);
if ($start_request >= 0) {
my $end_request = index($line, " ", $start_request + length($request));
$result = substr($line, $start_request + length($request), $end_request-$start_r
#print "$start_request, $end_request ’$result’\n";
} else {
#print "ERROR: Unrecognized Line: $line\n";
}
}
if (defined $result) {
if ($result eq "200") {
$good++;
} else {
$bad++;
}
} else {
$ugly++;
}
#!/usr/bin/perl
use strict;
use warnings;
my $total = 0;
my $count = 0;
my $min;
my $max;
my $filename = "examples/files/numbers.txt";
open(my $fh, "<", $filename) or die "Could not open ’$filename’\n";
while (my $line = <$fh>) {
chomp $line;
$total += $line;
if (not $count) {
$min = $line;
$max = $line;
}
$count++;
($x, $y, $z) # We can also use scalar variables as elements of a list
#!/usr/bin/perl
use strict;
use warnings;
33
Chapter 7. Lists and Arrays
Blue
Yellow
Brown
White
#!/usr/bin/perl
use strict;
use warnings;
my $owner = "Moose";
my @tenants = qw(Foo Bar);
my @people = ($owner, ’Baz’, @tenants); # Moose Baz Foo Bar
1
2
3
4
5
6
7
8
9
10
#!/usr/bin/perl
use strict;
use warnings;
my $color;
#!/usr/bin/perl
use strict;
use warnings;
my $color;
if (defined $ARGV[0]) {
$color = $ARGV[0];
}
#!/usr/bin/perl
use strict;
use warnings;
my $color;
GetOptions("color=s" => \$color) or die "Usage: $0 [--color COLOR]\n";
perldoc Cwd
http://perldoc.perl.org/Cwd.html
Foo,Bar,10,home
Orgo,Morgo,7,away
Big,Shrek,100,US
Small,Fiona,9,tower
#!/usr/bin/perl
use strict;
use warnings;
my $file = ’process_csv_file.csv’;
if (defined $ARGV[0]) {
$file = $ARGV[0];
}
my $sum = 0;
open(my $data, ’<’, $file) or die "Could not open ’$file’\n";
while (my $line = <$data>) {
chomp $line;
while (<>) {
$sum += (split ",")[2];
}
print "$sum\n";
Foo,Bar ,10,home
Orgo,"Morgo, Hapci",7,away
Big,Shrek,100,US
Small,Fiona,9,tower
#!/usr/bin/perl
use strict;
use warnings;
use Text::CSV_XS;
my $csv = Text::CSV_XS->new();
my $file = ’process_csv_file_module.csv’;
if (defined $ARGV[0]) {
$file = $ARGV[0];
}
my $sum = 0;
open(my $data, ’<’, $file) or die "Could not open ’$file’\n";
while (my $line = <$data>) {
chomp $line;
if ($csv->parse($line)) {
my @columns = $csv->fields();
$sum += $columns[2];
} else {
warn "Line could not be parsed: $line\n";
}
}
print "$sum\n";
7.14. Join
my @fields = qw(Foo Bar foo@bar.com);
my $line = join ";", @fields;
print "$line\n"; # Foo;Bar;foo@bar.com
Now I can tell you that what you have is actually a 1 dimensional space fight
and you are trying to guess the distance of the enemy space ship.
As it is not a sitting duck, after every shot the spaceship can randomly move +2-2.
For trainng purposes you might want to limit the outer spaces to 0-100.
Make sure the enemy does not wander off the training field.
Give warning if the user shoots out of space.
Keep track of the minimum and maximum number of hits (in a file).
#!/usr/bin/perl
use strict;
use warnings;
my $color;
my $filename = "examples/colors.txt";
my $force;
GetOptions(
"color=s" => \$color,
"filename=s" => \$filename,
"force" => \$force,
) or exit;
my @colors;
while (my $color = <$fh>) {
chomp $color;
if (not $color) {
print "Please select a number:\n";
foreach my $i (0..$#colors) {
print "$i) $colors[$i]\n";
}
my $num = <STDIN>;
chomp($num);
if (defined $colors[$num]) {
$color = $colors[$num];
} else {
print "Bad selection\n";
exit;
}
}
$t = time(); # 1021924103
# returns a 10 digit long number,
# the number of seconds since 00:00:00 UTC, January 1, 1970
$z = localtime(time - 60*60*24*365);
# returns the string for a year ago, same time, well almost
# 0 1 2 3 4 5 6 7 8 (the index)
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
# The localtime function is aware of what is on the left side of the = sign !!!!
if (@a) {
}
while (@a) {
42
Chapter 8. Advanced Arrays
# example
@a = qw(One Two Three);
print @a; # OneTwoThree" print LIST
print 0+@a; # 3 SCALAR + SCALAR
print scalar(@a); # 3 scalar(SCALAR)
#!/usr/bin/perl
use strict;
use warnings;
my $file = "numbers.txt";
open (my $other_fh, ’<’, $file) or die "Could not open ’$file’";
# reading in LIST context all the lines at once
my @rows = <$other_fh>;
chomp @rows;
print "READ " . @rows . " lines\n";
#!/usr/bin/perl
use strict;
use warnings;
my $file = "numbers.txt";
# slurp mode
my $all;
{
open(my $fh, ’<’, $file) or die "Could not open ’$file’\n";
local $/ = undef;
$all = <$fh>;
}
8.6. File::Slurp
Example 8-3. examples/arrays/file_slurp.pl
#!/usr/bin/perl
use strict;
use warnings;
my $text = slurp($filename);
push is the opposite of pop it adds element(s) to the end of the array
It returns number of elements after the push.
Example:
#!/usr/bin/perl
use strict;
use warnings;
#!/usr/bin/perl
use strict;
use warnings;
my @stack;
while (1) {
print ’$ ’;
my $in = <STDIN>;
chomp $in;
if ($in eq "c") {
pop @stack;
next;
} # fetch the last value
if ($in eq "*") {
my $x = pop(@stack);
my $y = pop(@stack);
push(@stack, $x*$y);
next;
}
if ($in eq "+") {
my $x = pop(@stack);
my $y = pop(@stack);
push(@stack, $x + $y);
next;
}
if ($in eq "/") {
my $x = pop(@stack);
my $y = pop(@stack);
push(@stack, $y / $x);
next;
}
if ($in eq "-") {
my $x = pop(@stack);
my $y = pop(@stack);
push(@stack, $y - $x);
next;
}
if ($in eq "=") {
print pop(@stack), "\n";
next;
}
push @stack, $in;
}
Example:
#!/usr/bin/perl
use strict;
use warnings;
#!/usr/bin/perl
use strict;
use warnings;
chomp $new;
push @people, $new;
}
print "\n";
}
8.11. shift
Example 8-8. examples/arrays/shift_argv.pl
#!/usr/bin/perl
use strict;
use warnings;
#!/usr/bin/perl
use strict;
use warnings;
my @sorted_by_length
= sort {length($a) <=> length($b)} @data;
my @sorted_by_length_and_ascii
= sort {
length($a) <=> length($b)
or
$a cmp $b
} @data;
my @sorted_abc_ascii
= sort {
lc($a) cmp lc($b)
or
$a cmp $b
} @data;
my $var = T ? A : B;
23 34 9512341
3 34 2452345 5353 67 22
42136357013412
42 5 65 64
#!/usr/bin/perl
use strict;
use warnings;
my @count;
foreach my $i (0..9) {
print "$i ", ($count[$i] ? $count[$i] : 0), "\n";
}
8.16. $_
Default variable
foreach (@people) {
print;
}
foreach $_ (@people) {
print $_;
}
#!/usr/bin/perl
use strict;
use warnings;
Standard deviation:
sum (for each i) (Xi-average) * (Xi-average)
divide by n (the number of elements)
take the square root of the result
Sort them first based on the first letter and among values with the same
leading letter sort them according to the numbers.
File:
A1
A27
C1
B1
B12
A38
B3
A3
#!/usr/bin/perl
use strict;
use warnings;
my @data = <STDIN>;
chomp @data;
if (not @data) {
print "No values were given\n";
exit;
}
my $total = 0;
foreach my $v (@data) {
$total += $v;
}
my $sqtotal = 0;
foreach my $v (@data) {
$sqtotal += ($average-$v) ** 2;
}
my $std = ($sqtotal / @data) ** 0.5;
#!/usr/bin/perl
use strict;
use warnings;
my $file = ’sort_mixed_strings.txt’;
if (@ARGV) {
$file = shift;
}
open(my $fh, ’<’, $file) or die "Could not open ’$file’\n";
my @data = <$fh>;
chomp @data;
my @sorted = sort {
substr($a, 0, 1) cmp substr($b, 0, 1)
or
substr($a, 1) <=> substr($b, 1) } @data;
foreach my $v (@sorted) {
print "$v\n";
}
8.22. grep
Example 8-16. examples/arrays/grep_perl.pl
#!/usr/bin/perl
use strict;
use warnings;
my @numbers = (1..30);
my @odd_numbers = grep { $_ % 2 } @numbers;
foreach my $num (@odd_numbers) {
print "$num\n";
}
8.23. map
Example 8-17. examples/arrays/map_perl.pl
#!/usr/bin/perl
use strict;
use warnings;
my @numbers = (1..30);
my @doubles = map {$_ * 2} @numbers;
8.24. List::Util
List::Util provides functions such as
• max
• min
• sum
#!/usr/bin/perl
use strict;
use warnings;
my @matrix;
$matrix[0][0] = 0;
$matrix[1][1] = 11;
$matrix[1][2] = 12;
#print "$matrix\n";
print "$matrix[0]\n"; # ARRAY(0x814dd90)
print "$matrix[1][1]\n"; # 11
8.26. splice
Removes the elements designated by OFFSET and LENGTH (and returns them).
Replaces them with the content of the 4th parameter.
#!/usr/bin/perl
use strict;
use warnings;
my @names = qw(Foo Bar Baz Moo Qux Barney Hoppy Bammbamm Dino);
my @more_names = qw(Fred Wilma);
9.1. Subroutines
Example 9-1. examples/subroutines/subroutines.pl
#!/usr/bin/perl
use strict;
use warnings;
sub add {
my ($x, $y) = @_;
my $z = $x+$y;
return $z;
}
sub add2 {
my $x = shift;
my $y = shift;
return $x+$y;
}
sub add_ugly {
return $_[0]+$_[1];
}
sub sum {
my $sum = 0;
foreach my $v (@_) {
$sum += $v;
}
return $sum;
}
56
Chapter 9. Functions and Subroutines
#!/usr/bin/perl
use strict;
use warnings;
my $result = factorial($n);
print $result;
sub factorial {
my ($n) = @_;
if ($n == 1) {
return 1;
}
my $prev = factorial($n - 1);
return $n * $prev;
}
#!/usr/bin/perl
use strict;
use warnings;
sub fib {
my $n = shift;
if ($n == 0 or $n == 1) {
return 1
}
#!/usr/bin/perl
use strict;
use warnings;
print "@data\n";
print "@sorted\n";
sub by_number {
return $a <=> $b;
}
#!/usr/bin/perl
use strict;
use warnings;
my @numbers = fib(10);
print "@numbers\n";
sub fib {
my $num = shift;
my @fib;
if ($num == 1) {
return (1);
}
if ($num == 2) {
return (1, 1);
}
@fib = (1, 1);
foreach (3..$num) {
push @fib, $fib[-1]+$fib[-2];
}
return @fib;
}
#!/usr/bin/perl
use strict;
use warnings;
my $result;
my $x = 19;
my $y = 23;
eval {
$result = unstable_add_function($x, $y);
print "unstable done\n";
};
if ($@) {
chomp $@;
warn "Exception ’$@’ received\n";
$result = slow_but_stable_add($x, $y);
print "slow done\n";
}
sub unstable_add_function {
if (rand() < 0.2) {
die "broken";
}
return $_[0]+$_[1];
}
sub slow_but_stable_add {
sleep (2);
return $_[0]+$_[1];
}
Features of an object:
my %user = (
"fname", "Foo",
"lname", "Bar",
);
my %user = (
fname => "Foo",
lname => "Bar",
);
$user{fname} = ’Moo’;
$user{email} = ’foo@bar.com’;
60
Chapter 10. Associative Arrays (Hashes)
my %user = @person;
my @foobar = %user;
print "@foobar\n"; # fname Foo lname Bar
$user{phone} = ’123-456’;
%user = (phone => ’123-456’); # removes all previous elements from the hash
In SCALAR context:
if (%h) {
# the hash is not empty
}
if (exists $phones{Foo}) {
if (defined $phones{Foo}) {
}
}
delete $phones{Foo};
#!/usr/bin/perl
use strict;
use warnings;
my %grades;
$grades{"Foo Bar"}{Mathematics} = 97;
$grades{"Foo Bar"}{Literature} = 67;
$grades{"Peti Bar"}{Literature} = 88;
$grades{"Peti Bar"}{Mathematics} = 82;
$grades{"Peti Bar"}{Art} = 99;
$VAR1 = {
’Peti Bar’ => {
’Art’ => 99,
’Literature’ => 88,
’Mathematics’ => 82
},
#!/usr/bin/perl
use strict;
use warnings;
my %count;
yellow y
brown z
black b
blue e
y) yellow
z) brown
b) black
e) blue
Foo,23
Bar,70
Baz,92
Bozo,17
Gozo,52
Dardon,20
Mekodra,23
each IP adddress.
# In a log file there are rows in which the first 16 and last 16 characters
# describe addresses while everything in between describes several commands
# Each command is built up by a leading character (A, B, C, D, etc) and a number
# of digits. The number of digits depend on the leading character.
#
# In this example we split up the data to commands and count how many times
# each command type was given.
#
1234567890123456A001B0002D00004C0000051234567890123456
1234567890123456A001A002D00004C0000051234567890123456
#!/usr/bin/perl
use strict;
use warnings;
my $str = ’fname=Foo&lname=Bar&email=foo@bar.com’;
my @pairs = split "&", $str;
my %data;
foreach my $p (@pairs) {
my ($k, $v) = split "=", $p;
$data{$k} = $v;
}
use Data::Dumper;
print Dumper \%data;
#!/usr/bin/perl
use strict;
use warnings;
my $color;
my $filename = "examples/color_map.txt";
my $force;
GetOptions(
"color=s" => \$color,
"filename=s" => \$filename,
"force" => \$force,
);
my %colors;
if (not $color) {
print "Please select a number:\n";
#!/usr/bin/perl
use strict;
use warnings;
my %score_of;
while (my $line = <$fh>) {
chomp $line;
my ($name, $score) = split ",", $line;
$score_of{$name} = $score;
}
#!/usr/bin/perl
use strict;
use warnings;
my %count;
while (my $line = <$fh>) {
chomp $line;
my $length = index ($line, " ");
my $ip = substr($line, 0, $length);
$count{$ip}++;
}
#!/usr/bin/perl
use strict;
use warnings;
my %count;
my %length = (
A => 3,
B => 4,
C => 6,
D => 5,
);
my $filename = "examples/hashes/variable_width_fields.log";
if ($ARGV[0]) {
$filename = $ARGV[0];
}
open my $data, ’<’, $filename or die "Could not open ’$filename’ $!";
LINE:
while (my $line = <$data>) {
chomp $line;
if (substr($line, 0, 1) eq "#") {
next;
}
#print $line;
my $cmds = substr($line, 16, -16);
#print $cmds;
while ($cmds) {
my $c = substr($cmds,0,1, "");
#print "$c\n";
#print "$cmds\n";
if (not defined $length{$c}) {
warn "....";
next LINE;
}
my $cmd = substr($cmds,0, $length{$c}, "");
$count{$c}++;
print "$c : $cmd\n";
}
}
11.2. Examples
Which one is a number: 23, 2.3 2.3.4 2.4e3 abc ?
if ($str !~ /s r/) {
print "No match\n";
}
#!/usr/bin/perl
use strict;
use warnings;
70
Chapter 11. Regular Expressions
11.5. Tools
Regex Coach: http://weitz.de/regex-coach/
Regex: /x/
Input: "abcde"
Input: "abxcde"
Input: "xabcde"
Regex: /^x/
Input: "abcde"
Input: "abxcde"
Input: "xabcde"
Input: " xabcde"
^ at the beginning of the regular expression means, match at the beginning of the string.
Regex: /x.x/
Input: "abcde"
Input: "abxcxbde"
Input: "xabcde"
Input: "xabxcxde"
Regex: /x\.x/
Regex: /-[abcdef@.]-/
Input: "ab -q- "
Input: "ab -z-a- "
Input: "ab -.- "
Input: "ab -- "
Regex: /-[a-f@.]-/
Regex: /-[^abc]-/
Input: "abc -a- z"
Input: "abc -z- z"
Regex: /-.*-/
Input: "ab"
11.11. Quantifiers
Quantifiers apply to the thing in front of them
* 0-
+ 1-
? 0-1
{n,m} n-m
{n,} n-
{n} n
Regex: /-[abc]+-/
Input: "-a-" OK
Input: "-b-" OK
Input: "-ab-" OK
Input: "-aa-" OK
Input: "-x-"
• has an ’a’
• starts with an ’a’
• has ’th’
• has an ’a’ or an ’A’
• has a ’*’ in it
• starts with an ’a’ or an ’A’
• has both ’a’ and ’e’ in it
• has an ’a’ followed by an ’e’ somewhere in it
• does not have an ’a’
• does not have an ’a’ nor ’e’
• has an ’a’ but not ’e’
• has at least 2 consequtive vowels (a,e,i,o,u)
• has at least 3 vowels
• has at least 6 characters
• has at exactly 6 characters
• Bonus: all the words with either ’aba’ or ’ada’ in them
• Bonus: all the words with either ’aba’ or ’eda’ in them
• Bonus: has a double character (e.g. ’oo’)
• Bonus: for every word print the first vowel
#!/usr/bin/perl
use strict;
use warnings;
if ($line =~ /REGEX2/) {
/a[bd]a/
11.16. Capturing
Bounus: for every word print the first vowel
if ($line =~ /([aeiou])/) {
print $1;
}
if ($line =~ /(.)\1/) {
print $1;
}
if ($line =~ /(.*)=(.*)/) {
print "left: $1\n";
print "right: $2\n";
}
11.17. Anchors
^ # at the beginning of the pattern means beginning of the string
$ # at the end of the pattern means the end of the string
/^\s*$/ # the string contains only white spaces (it looks like an empty string)
\b # Word delimiter
/\bstruct\b/ # match every place the word "struct" but not "structure" or "construct"
/\b\w+\b/ # A single "word"
/a[^xa]a/ # "aba", "aca" but not "aaa", "axa" what about "aa" ?
# ^ as the first character in a character class means
# a character that is not in the list
/a[a^x]a/ # aaa, a^a, axa
Expression Meaning
\w Word characters: [a-zA-Z0-9_] (but \w is locale
dependent)
\d Digits: [0-9]
\s [\f\t\n\r ] form-feed, tab, newline, carriage return
and SPACE
\W [^\w]
\D [^\d]
\S [^\s]
[:class:] POSIX character classes (alpha, alnum...)
\p{...} Unicode definitions (IsAlpha, IsLower, IsHebrew,
...)
#!/usr/bin/perl
use strict;
use warnings;
#!/usr/bin/perl
use strict;
use warnings;
#!/usr/bin/perl
use strict;
use warnings;
# This solution only check is the string consists of characters used in as Roman numbers
# but does not check if the number is actually a valid number. (e.g. IVI is not valid)
# I yet to see a definition on how to validate a Roman number.
if (is_roman($number)) {
print "Roman number\n";
}
}
11.26. Regexp::Common
Example 11-6. examples/regex/regexp_common.pl
#!/usr/bin/perl
use strict;
use warnings;
use Regexp::Common;
my $file = ’regexp_common.txt’;
if (@ARGV) {
$file = shift;
}
open(my $data, ’<’, $file) or die "Could not open $file\n";
one
(two)
(three))
((three)
)four(
poop
/usr/bin/perl
if ($line =~ /\/usr\/bin\/perl/) {
}
if ($line =~ m{/usr/bin/perl}) {
}
#!/usr/bin/perl
use strict;
use warnings;
#../regex/examples/text/american-english
my $filename = shift or die;
my $data;
{
/
(X\d+) # product number
.* # any character
\1 # the same product number
/x
11.32. Substitute
• s/PATTERN/REPLACEMENT/
$line = "abc123def";
/a.*b/ axy121413413bq
/a.*?b/ axy121413413bq
They both match the same string
Better to write:
s/^\s+// leading
s/\s+$// tailing
both ends:
s/^\s*(.*)\s*$/$1/ " abc " => "abc " because of the greediness
mv A, R3
mv R2, B
mv R1, R3
mv B, R4
add A, R1
add B, R1
add R1, R2
add R3, R3
mv X, R2
#!/usr/bin/perl
use strict;
use warnings;
s/(R[123])/$map{$1}/g
fname = Foo
lname = Bar
email=foo@bar.com
#!/usr/bin/perl
use strict;
use warnings;
# data: field_value_pairs.txt
my $filename = shift or die "Usage: $0 filename\n";
my $str = ’fname=Foo&lname=Bar&email=foo@bar.com’;
1.2.7.6
4.5.7.23
1.2.7
2.3.5.7.10.8.9
09:20 Introduction
11:00 Exercises
11:15 Break
11:35 Scalars
12:30 Lunch Break
13:30 Exercises
14:10 Solutions
14:30 Break
14:40 Arrays
15:40 Exercises
17:00 Solutions
17:30 End
09:20-11:00 Introduction
11:00-11:15 Exercises
11:15-11:35 Break
...
Solutions 95 minutes 9%
Break 65 minutes 6%
...
Given a filename, a section name and a key, please print out the value.
Example ini file:
# comment
[alpha]
base= moon
ship= alpha 3
[earth]
# ?
base=earth
ship= x-wing
#!/usr/bin/perl
use strict;
use warnings;
my $str = ’fname=Foo&lname=Bar&email=foo@bar.com’;
my %data = split /[=&]/, $str;
use Data::Dumper;
print Dumper \%data;
#!/usr/bin/perl
use strict;
use warnings;
my $path = "/home/foo/.mozilla/cache/data.txt";
# Directory name:
print "$path\n";
print "$filename\n";
print "$dirname\n";
use File::Basename;
print basename($path) . "\n";
print dirname($path) . "\n";
#!/usr/bin/perl
use strict;
use warnings;
my @snmps = <$fh>;
chomp @snmps;
sub by_snmp_number {
my @a = split /\./, $a;
my @b = split /\./, $b;
foreach my $i (0..@a-1) {
return 1 if $i >= @b;
next if $a[$i] == $b[$i];
return $a[$i] <=> $b[$i];
}
return 0;
}
print "\n------------------\n";
my @data = map { {"ip" => $_, "data" => [split /\./, $_]} } @snmps;
my @sorted_data = sort {g($a, $b)} @data;
my @sorted_snmps_take_two = map {$_->{ip}} @sorted_data;
print join "\n", @sorted_snmps_take_two;
print "\n------------------\n";
sub g {
my ($a, $b) = @_;
my @a = @{ $a->{data} };
my @b = @{ $b->{data} };
foreach my $i (0..@a-1) {
return 1 if $i >= @b;
next if $a[$i] == $b[$i];
return $a[$i] <=> $b[$i];
}
return 0;
}
#!/usr/bin/perl
use strict;
use warnings;
my @entries;
my %stat;
open(my $fh, "<", $filename) or die "Could not open ’$filename’ $!";
sub process_day {
my @day;
foreach my $e (@entries) {
my ($time, $title) = split " ", $e, 2;
if (@day) {
$day[-1]{end} = $time;
my ($start_hour, $start_min) = split ":", $day[-1]{start};
my ($end_hour, $end_min) = split ":", $day[-1]{end};
$day[-1]{total} = $end_hour*60+$end_min - ($start_hour*60+$start_min);
if ($day[-1]{title} =~ /Break|Exercises|Solutions/) {
$stat{$day[-1]{title}} += $day[-1]{total};
} else {
$stat{Lectures} += $day[-1]{total};
}
$stat{Total} += $day[-1]{total};
#!/usr/bin/perl
use strict;
use warnings;
if (@ARGV != 2) {
print "Usage: $0 section key\n";
exit;
}
my ($section, $key) = @ARGV;
my $in_section = 0;
if ($line =~ /^\[$section\]$/) {
$in_section = 1;
next;
}
if ($line =~ /^\[/) {
$in_section = 0;
next;
}
if ($in_section and $line =~ /^$key\s*=\s*(.*)$/) {
print "$1\n";
last;
}
}
#!/usr/bin/perl
use strict;
use warnings;
# scalars only but finds only the first variable on every line
#while (<>) {
# if (/(\$\w+)\b/) {
# if (not defined $h{$ARGV}{$1}) {
# $h{$ARGV}{$1}=1;
# print "$ARGV: $1\n";
# }
# }
#}
Expression Meaning
a Just an ’a’ character
. any character except new-line
[bgh.] one of the characters listed in the character class
b,g,h or .
[b-h] The same as [bcdefgh]
[a-z] Lower case letters
[b-] The letter b or -
[^bx] Anything except b or x
\w Word characters: [a-zA-Z0-9_]
\d Digits: [0-9]
\s [\f\t\n\r ] form-feed, tab, newline, carriage return
and SPACE
\W [^\w]
\D [^\d]
\S [^\s]
[:class:] POSIX character classes (alpha, alnum...)
\p{...} Unicode definitions (IsAlpha, IsLower, IsHebrew,
...)
a* 0-infinite ’a’ characters
a+ 1-infinite ’a’ characters
a? 0-1 ’a’ characters
a{n,m} n-m ’a’ characters
() Grouping and capturing
| Alternation
\1, \2 Capture buffers
$1, $2 Capture variables
^$ Beginning and end of string ancors
It returns 0 on success and the exit code of the external program on failure. Hence the strange way we
check if it failes.
Passing the program name and the parameters as an array is more secure as it does not involve invocation
of a shell. There is no shell processing involved;
system("some_app.exe --option");
UNIX DOS
unlink FILENAME rm del
rename OLDFILE, NEWFILE mv ren
chmod MODE, FILE chmod -
chown UID, GID, FILE chown -
93
Chapter 12. Shell to Perl
chdir DIRNAME cd cd
mkdir DIRNAME, PERM mkdir mkdir
rmdir DIRNAME rmdir rmdir
link OLDNAME, ln -
NEWNAME
symlink OLDNAME, ln -s -
NEWNAME
readlink LINKNAME ls -l -
glob WILDCARDS ls -1 dir
opendir, readdir ls -1 dir
%ENV, $ENV{HOME}
my $uid = getpwnam($username);
my $gid = getgrnam($groupname);
#!/usr/bin/perl
use strict;
use warnings;
# File globbing
my @xml_files_in_current_dir = glob "*.xml";
my $bin_dir = "/home/foo/bin";
my @perl_files = glob "$bin_dir/*.pl $bin_dir/*.pm";
# my @xml_files_using_old_syntax = <*.xml>;
#!/usr/bin/perl
use strict;
use warnings;
In order to read the content of a directory (that is the list of the files)
first we have to open the directory similarly to the way we opened a file
but using the opendir function
This way we get a directory handle which we can use in subsequent operations.
Once the directory was opened successfully we can use the function readdir
in a loop to get the names of the files in that directory
#!/usr/bin/perl
use strict;
use warnings;
12.6. File::HomeDir
Example 12-4. examples/shell/file_homedir.pl
#!/usr/bin/perl
use strict;
use warnings;
use File::HomeDir;
my $home = File::HomeDir->my_home;
my $docs = File::HomeDir->my_documents;
print "$home\n";
print "$docs\n";
directory hierarchy
• File::Find
• reference to subroutine
#!/usr/bin/perl
use strict;
use warnings;
my $dir = ".";
if (defined $ARGV[0]) {
$dir = $ARGV[0];
}
sub change_file {
if (not -f $_) {
return;
}
if (substr($_, -3) ne ".pl") {
return;
}
print "$_\n";
my $data;
if (open my $fh, "<", $_) {
local $/ = undef;
$data = <$fh>;
} else {
warn "Could not open ’$_’ for reading\n";
return;
}
12.10. File::Tools
Includes all the above
.
subdir_1
file_1_in_subdir_1
file_2_in_subdir_1
subdir_2
subdir_2_1
file_1_in_subdir_2_1
file_1_in_subdir_2
#!/usr/bin/perl
use strict;
use warnings;
my $dir = ’.’;
if (@ARGV) {
$dir = $ARGV[0];
}
traverse_dir(”, $dir, 0);
sub traverse_dir {
my ($dir, $thing, $depth) = @_;
my $path = ($dir ? "$dir/$thing" : $thing);
#!/usr/bin/perl
use strict;
use warnings;
use File::Find;
if (not @ARGV) {
@ARGV = (".");
}
sub find_name {
print " " x (split("/", $File::Find::name) -1);
print "$_\n";
return;
}
#!/usr/bin/perl
use strict;
use warnings;
use File::Find::Rule;
my $dir = ’.’;
if (@ARGV) {
$dir = shift;
}
For this there is a bunch of so called -X operators. Usually you use them in
an if statement:
if (-e "file.txt") {
print "File exists !\n";
}
$size = -s $filename;
#!/usr/bin/perl
use strict;
use warnings;
my $filename = "input.txt";
open my $fh, "<", $filename or die $!;
100
Chapter 13. More about files
my $line = <$fh>;
chomp $line;
#!/usr/bin/perl
use strict;
use warnings;
# reading in 30 characters:
WHENCE:
0 from beginning of file
1 from current location
2 from end of file
OFFSET:
+/- number of bytes to move
13.4. truncate
# Sometimes you need to
truncate FILEHANDLE, LENGTH;
#!/usr/bin/perl
use strict;
use warnings;
my $new = $ARGV[0];
my $filename = "file.txt";
open my $fh, "+<", $filename or die "Could not open $!\n";
my $old = <$fh>;
(hint: only symbolic links as hard links are bound to the inode
number which is local to each partition)
List all the logfiles in the current directory that are older than 3 days
List all the log files in this directory and subdirectories that
are more than 3 days old.
#!/usr/bin/perl
use strict;
use warnings;
my $filename = "counter.txt";
if (not -e $filename) {
open my $fh, ">", $filename or die "Could not create counter file: $!";
print $fh 0;
}
open my $fh, "+<", $filename or die "Could not open counter: $!\n";
my $c = <$fh>;
chomp $c;
seek $fh, 0, 0;
truncate $fh, 0;
$c++;
print $c;
#!/usr/bin/perl
use strict;
use warnings;
unless (@ARGV) {
print "Usage: $0 <counter-id>\n";
exit;
}
my $filename = "multiple_counter.txt";
if (not -e $filename) {
open my $fh, ">", $filename or die "Could not create counter file: $!";
print $fh 0;
}
open my $fh, "+<", $filename or die "Could not open counter: $!\n";
my @c = <$fh>;
chomp @c;
$c[$id]++;
print $c[$id];
foreach my $v (@c) {
if (defined $v) {
print $fh "$v\n";
} else {
print $fh "\n";
}
}
close $fh;
#!/usr/bin/perl
use strict;
use warnings;
find({
wanted => \&old_files,
no_chdir => 1,
}, $ARGV[0] || ’.’);
sub old_files {
if (substr($_, -4) ne ".log") {
return;
}
if (-M $_ > 3) {
print "$_\n";
}
return;
}
Probably better this way, so the reader will know where each function comes from and we reduce the risk
of redefining other functions by importing exactly the functions we want.
also written as
You can also make sure not to import anything and the use fully qualified names.
#!/usr/bin/perl
use strict;
use warnings;
use Math::BigInt;
my $x = Math::BigInt->new("1234567890");
my $y = Math::BigInt->new("8234567890");
$x->badd($y);
print $x->bstr, "\n"; # 9469135780
107
Chapter 14. Using Perl modules, using CPAN
• CPAN http://www.cpan.org/
• Searching CPAN http://search.cpan.org/
• Randy Kobes CPAN http://kobesearch.cpan.org/
• POD = Plain Old Documentation
• CPAN Testers http://testers.cpan.org/
• CPAN Ratings http://cpanratings.perl.org/
• CPANTS http://cpants.perl.org/
• RT (Request Tracker) http://rt.cpan.org/
• Annotate POD http://annocpan.org/
• CPAN::Forum http://www.cpanforum.com/
• Mailing lists http://lists.cpan.org/
• PerlMonks http://www.perlmonks.org/
• Perl Mongers http://www.pm.org/
• Perl Mongers in Israel http://www.perl.org.il/
C:> ppm
ppm> install Name-Of-Module
ppm> install 3
There are additional sites with ppm repositories once can find on Kobes Search
Add the repository to ppm and install modules from that place as well:
ppm> rep add uwin http://theoryx5.uwinnipeg.ca/ppms/
ppm> install IO-Socket-SSL
in ActiveState 5.6.x
ppm> set rep name URL
the http_proxy environment variable and ppm will use the proxy:
set http_proxy=http://proxy.company.com:8080
In the code:
Module::Build
perl Build.PL --install_base /home/foobar/perl5lib --install_path lib=/home/foobar/perl5lib/lib
./Build
./Build test
./Build install
# relative path
use FindBin;
use File::Spec;
use lib File::Spec->catfile($FindBin::Bin, ’..’, ’lib’);
# relative path
use File::Spec;
use File::Basename;
use lib File::Spec->catfile(
File::Basename::dirname(File::Spec->rel2abs($0)),
’..’,
’lib’);
$ cpan
cpan> install Module::Name
14.8. CPAN.pm
Example 14-2. examples/cpan/ENV
export PERL5LIB=/home/gabor/perl5lib/lib
# ~/.cpan/CPAN/MyConfig.pm.
$CPAN::Config = {
’build_cache’ => q[10],
’build_dir’ => q[/home/gabor/.cpan/build],
’cache_metadata’ => q[1],
’cpan_home’ => q[/home/gabor/.cpan],
’dontload_hash’ => { },
’ftp’ => q[/usr/kerberos/bin/ftp],
’ftp_proxy’ => q[],
’getcwd’ => q[cwd],
’gpg’ => q[/usr/bin/gpg],
’gzip’ => q[/bin/gzip],
’histfile’ => q[/home/gabor/.cpan/histfile],
’histsize’ => q[100],
’http_proxy’ => q[],
’inactivity_timeout’ => q[0],
’index_expire’ => q[1],
’inhibit_startup_message’ => q[0],
’keep_source_where’ => q[/home/gabor/.cpan/sources],
’links’ => q[/usr/bin/links],
’make’ => q[/usr/bin/make],
’make_arg’ => q[],
’make_install_arg’ => q[],
’makepl_arg’ => q[PREFIX=/home/gabor/perl5lib LIB=/home/gabor/perl5lib/lib],
’ncftpget’ => q[/usr/bin/ncftpget],
’no_proxy’ => q[],
’pager’ => q[/usr/bin/less],
’prerequisites_policy’ => q[follow],
’scan_cache’ => q[atstart],
’shell’ => q[/bin/bash],
’tar’ => q[/bin/tar],
’term_is_latin’ => q[1],
’unzip’ => q[/usr/bin/unzip],
’urllist’ => [q[http://mirror.mirimar.net/cpan/]],
’wget’ => q[/usr/bin/wget],
};
1;
__END__
#!/usr/bin/perl
=pod
search.cpan.org
search Acme::EyeDrops
download the latest Acme-EyeDrops gziped file (for me it was Acme-EyeDrops-1.01.tar.gz)
mkdir modules (create a local directory where we’ll install the module)
tar xzf Acme-EyeDrops-1.01.tar.gz
cd Acme-EyeDrops-1.01
perl Makefile.PL PREFIX=/home/user/modules LIB=/home/user/module/lib
(the full path to the directory you created for the modules)
make
make test
make install
Create a script called hello_world.pl that asks for your name and then
prints Hello NAME.
=cut
use strict;
use warnings;
print sightly({
Shape => ’camel’,
SourceFile => ’hello_world.pl’,
});
#!/usr/bin/perl
use strict;
use warnings;
my $adduser = ’/usr/sbin/adduser’;
my %opts;
GetOptions(\%opts,
’fname=s’,
’lname=s’,
) or usage();
print "$cmd\n";
system $cmd;
sub usage {
my ($msg) = @_;
if ($msg) {
print "$msg\n\n";
114
Chapter 15. Applications
}
print "Usage: $0 --fname FirstName --lname LastName\n";
exit;
}
#!/usr/bin/perl
use strict;
use warnings;
#!/usr/bin/perl
use strict;
use warnings;
#
# Reporting disk usage on the mail server
#
# Run the script in a cron job
#
# 1) Report to Boss if there are people with large files
#
# 2) If a user has a file that is too big then ask him to remove the
# large e-mail from the mail server via web access
# This one has not been implemented yet
#
######################################################
my %file_size;
foreach my $path (</var/spool/mail/*>) { # each user has a file in that directory
if ($path =~ /Save/) { # disregard the Save directory
next;
}
if ($path =~ /\.pop$/) { # disregard temporary .pop files
next;
}
$file_size{$path} = -s $path;
}
my $txt = "x";
# sort files by size
foreach my $path (sort {$file_size{$b} <=> $file_size{$a}} keys %file_size) {
my $name = $path;
$name =~ s{/var/spool/mail/}{};
if ($txt) {
$txt = "Disk Usage of /var/spool/mail on the incoming mail server\n" .
"Reporting users over $report_to_boss_limit bytes\n\n" .
$txt;
sendmail (
To => $boss_email,
From => $from_email,
Subject => ’Disk Usage Report’ . localtime(),
Message => $txt,
);
}
#!/usr/bin/perl
use strict;
use warnings;
#!/usr/bin/perl
use strict;
use warnings;
my $to;
my $from;
my $help;
my $file;
GetOptions(
"to=s" => \$to,
"from=s" => \$from,
"help" => \$help,
"file=s" => \$file,
);
if ($help) {
usage();
}
if ($to and $from and $file) {
my ($subject, $message) = read_file($file);
my %mail = (
To => $to,
From => $from,
Subject => $subject,
Message => $message,
);
sendmail(%mail) or die $Mail::Sendmail::error;
} else {
usage();
}
sub usage {
print "Usage: $0\n";
print " --to TO\n";
print " --from FROM\n";
print " --file FILE\n";
print "\n";
print " --help\n";
print "\n";
print "The given FILE is going to be the content of the e-mail\n";
print "The first line of the file should be:\n";
print "Subject: and the subject itself\n";
print "\n";
exit;
}
sub read_file {
my ($file) = @_;
open(my $fh, "<", $file) or die "Could not open ’$file’\n";
my $subject = <$fh>;
local $/ = undef;
my $message = <$fh>;
$subject =~ s/^Subject: //;
#!/usr/bin/perl
use strict;
use warnings;
my @data = $sheet->next_row;
print join "|", @data;
print "\n";
}
}
#!/usr/bin/perl
use strict;
use warnings;
# You need to parse a log file where the fields are fixed length long
# and have no delimiters
# The definition is as follows:
# LABEL: 4 chars
# SOURCE: 8 digits
# DESTINATION: 8 digits
# TYPE: 4 chars
# VALUE: 8 digits
my $file = ’examples/pack.txt’;
ALD37845566974923342XYZ24023984
QRW49327408234028434ERD24448009
device = 234234
name = Big
address = 115.6.79.8
class = B
device = 234224
device = 234235
name = Big Green box
address = 115.6.79.1
class = G
owner = Boss
device = 334235
name = Small Yellow
address = 115.6.79.10
class = Y
#!/usr/bin/perl
use strict;
use warnings;
=head1 DESCRIPTION
device = 234234
name = Big
address = 115.6.79.8
class = B
=cut
if (@ARGV != 2) {
die "\n Usage: $0 filename name\n Try: $0 examples/config.txt Big\n\n";
}
my ($filename, $name) = @ARGV;
open(my $fh, "<", $filename) or die "Could not open ’$filename’ $!";
my %data;
while (my $line = <$fh>) {
chomp $line;
if ($line =~ /^\s*$/ and %data) {
if ($data{name} eq $name) {
foreach my $k (keys %data) {
printf "%-10s = %s\n", $k, $data{$k};
}
exit;
}
%data = ();
} else {
my ($field, $value) = split /\s*=\s*/, $line;
$data{$field} = $value;
}
}
Name,ID,Input,Output
Big Venta,12,Left,Right
Small Elevator,7343124,Bottom,Top
Giant Ant,423235,Lower floor,Upper floor
#!/usr/bin/perl
use strict;
use warnings;
my $csv = Text::CSV_XS->new;
my $key = "Name";
my $header = <$fh>;
chomp $header;
$csv->parse($header);
my @header = $csv->fields;
my %data;
$data{$h{$key}} = \%h;
}
#!/usr/bin/perl
use strict;
use warnings;
<html>
<head>
</head>
<body>
<TMPL_IF echo>
You typed <TMPL_VAR echo>
</TMPL_IF>
<form>
<input name="text">
<input type=submit" value="Echo">
</form>
</body>
</html>
This is a simple Perl script that should be installed to a CGIExec enabled directory of Apache. When the
user hits this page the first time it displays a white page with only entry-box and a submit button on it.
the user can fill the box,
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use HTML::Template;
if ($q->param("text")) {
my $text = $q->param("text");
$template->param(echo => $text);
}
print $template->output
<people>
<person id="1">
<fname>Josef</fname>
<lname>Kiss</lname>
<idnum>4342324234</idnum>
<children>
<child>
<id>3</id>
</child>
</children>
</person>
<person id="2">
<fname>Peter</fname>
<lname>Kiss</lname>
<idnum>8768996</idnum>
</person>
<person id="3">
<fname>Zoltan</fname>
<lname>Kiss</lname>
<idnum>09808760</idnum>
</person>
</people>
#!/usr/bin/perl
use strict;
use warnings;
#!/usr/bin/perl
use strict;
use warnings;
my $action;
GetOptions("action=s" => \$action);
if (not $action or $action !~ /^(create|insert|selecta|selecth)$/) {
print <<"USAGE";
Usage:
$0 --action create|insert|selecta|selecth
USAGE
exit;
}
my $dbfile = "sample.db";
if ($action eq "create") {
create();
exit;
}
sub create {
unlink $dbfile if -e $dbfile;
my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile","","", {});
$dbh->do("CREATE TABLE people (id INTEGER PRIMARY KEY, fname VARCHAR(100), lname VARCHAR
return;
}
sub insert {
$dbh->do("INSERT INTO people (id, fname, lname) VALUES(?, ?, ?)", undef, 1, "Gabor", "Sz
$dbh->do("INSERT INTO people (id, fname, lname) VALUES(?, ?, ?)", undef, 2, "Josef", "Ki
return;
}
sub fetch_arrays {
my $sth = $dbh->prepare("SELECT lname, fname FROM people WHERE id = ?");
$sth->execute(1);
while (my @result = $sth->fetchrow_array()) {
print "lname: $result[0], fname: $result[1]\n";
}
$sth->finish;
return;
}
sub fetch_hashref {
my $sth = $dbh->prepare("SELECT lname, fname FROM people WHERE id = ?");
$sth->execute(1);
while (my $result = $sth->fetchrow_hashref("NAME_lc")) {
print "lname: $result->{lname}, fname: $result->{fname}\n";
}
$sth->finish;
return;
}
15.15. Net::LDAP
Example 15-19. examples/applications/ldap.pl
#!/usr/bin/perl
use strict;
use warnings;
use Net::LDAP;
my $server = "ldap.itd.umich.edu";
my $ldap = Net::LDAP->new( $server ) or die "$@";
$ldap->bind;
my $result = $ldap->search(
base => "",
filter => "(&(cn=Ver*) (sn=Szab*))",
attr => ["mail"],
);
$ldap->add(
’cn=root, o=University of Michigan, c=US’,
attr => [
cn => ’Gabor Szabo’,
ou => ’My Place in the Universe’,
mail => ’gabor@pti.co.il’,
],
);
$ldap->unbind;
15.16. Tie::File
Example 15-20. examples/applications/tie.pl
#!/usr/bin/perl
use strict;
use warnings;
use Tie::File;
You have a bunch of text files in your directory mentioning the name:
"Microsoft Word"
"OpenOffice Write"
-i = inplace editing
-p = loop over lines and print each line (after processing)
-e = command line script
In a CSV file you would like to sum up the numbers in the 3rd column.
The END block gets executed at the end of the execution and only once.
You want to make sure all the rows are 4 elements long.
128
Chapter 16. Oneliners
Print out file name and line number of all the bad rows.
Huge repository of examples and explanations covering lots of areas where you’ll use Perl.
The ultimate source for Perl written by the experts. This is NOT for the beginner !
For people who need to maintain Perl code or who need to write maintainable Perl code.
130
Appendix A. Appendix
132
Table of Contents