Sum numbers in a file
Let's do now something slightly useful with our knowledge.
In this example we have a file called numbers.txt
that has numbers in it. Each line is a number:
3
7
23
-17
98
12
Let's add these numbers together and print out their sum: In order to accomplish this we need to have a variable to hold the sum of numbers so far that will start from 0, then go over the file line-by-line and add the content of each line to the variable holding the sum.
#!/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";
After including the standard beginning of almost every Perl program we declare a variable called $sum
where we are going to collect the sum
of the numbers. We initialize it to 0.
Then we have the name of the file hard-coded in a variable called $filename
The we call open
to open the file or die
to throw an exception of the open
failed. Regular thing
we have seen in the article open and read from files.
Then we go over it line-by-line using a while
loop.
This code will read in one line on every iteration. So $line
will always contain the a line which is a number and trailing newline.
Then we add that line to the $sum
variable using +=
. Because Perl is nice to us, it disregards the newline, and automatically converts
the string to a numeric value so we don't need to use any special expression for casting the string to a number.
When we finish the loop we have all the numbers in the $sum
variable that we can print.
Using List::Util
We have not learned it yet, and it is not in the video, but let me add two more solutions. In the first
one we use the sum
function of the standard List::Util module.
#!/usr/bin/perl
use strict;
use warnings;
use List::Util qw(sum);
my $filename = "numbers.txt";
open(my $fh, "<", $filename) or die "Could not open '$filename'\n";
my $sum = sum <$fh>;
print "The total value is $sum\n";
We open the file exactly the same way as we did in the previous example, but this pass the result of the read-file operator to the
sum
function. In this case we are actually reading from the file in list context
which means all the lines are read into memory at once and they are passed to the sum
function as individual elements. (Each line is one element.)
The sum
function then adds them together and returns the result.
Using Path::Tiny as well
In the third example we also use the path
function of the Path::Tiny module
that opens a file and returns an object on which we can call the lines
method. This will return the lines of the file.
#!/usr/bin/perl
use strict;
use warnings;
use List::Util qw(sum);
use Path::Tiny qw(path);
my $filename = "numbers.txt";
my $sum = sum path($filename)->lines;
print "The total value is $sum\n";