You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

227 lines
19 KiB

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Perl 5</title>
<link href="/styles/styles.css" rel="stylesheet" type="text/css">
<link href="/programming/styles/styles.css" rel="stylesheet" type="text/css">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="banner">
<h1 class="courselink">Perl 5 Essential Traning</h1>
<h2 class="lecturer">LinkedIn Learning : Bill Weinman</h2>
<h2 class="episodetitle">Quick Start</h2>
</div>
<article>
<h2 class="sectiontitle">Hello World</h2>
<p>We’ll start with the traditional hello world program, shown in figure 1.</p>
<pre class="inset">
1. #!/usr/bin/perl
2. # hello.pl - chapter 1 - perl 5 essential training
3.
4. use 5.16.3;
5. #use warnings;
6.
7. say "Hello World!";</pre>
<p class="caption">Figure 1 - hello world, written in Perl</p>
<p>This has some similarities to a bash script, the shebang line is present although in this case it shows the path to the Perl interpreter. In addition, Perl uses the same style of comments.</p>
<p>It’s worth noting that the shebang line looks like a comment and it is, in the sense that the interpreter will know not to interpret this line. However, when the hash is immediately followed by an exclamation mark, this tells bash (or whatever shell you are using) how to run the script. In this case, the instruction is to use the Perl interpreter.</p>
<p>This is not always necessary and can be omitted if the script is not going to be executed on a Unix system, but it is important to remember that many web servers run on Unix. In addition, Mac OS is based on Unix, so it is probably good practice to include it.</p>
<p>Use tells the interpreter to use a particular library or configuration. The first use statement tells it to use the syntax and features from Perl version 5.16.3. If the interpreter is updated or upgraded, let’s say to Perl 5.18, the script should still run so we have some backwards compatibility.</p>
<p>The next use statement is optional but is considered good practice because if it is omitted, Perl will allow you to get away with some syntactical bad practices!</p>
<p>The final line is say “Hello, World!”. Like echo, say will send a line of output to the default device, normally the screen and will add a newline. We can also use print which works in a similar way, but does not automatically add a newline. However, this could be added as an escape character in the same way as you would do with C or Java so</p>
<p class="inset">print “Hello, World!\n”;</p>
<p>is exactly equivalent to</p>
<p class="inset">say "Hello, World!";</p>
<p>Note, also, that each line ends with a semi-colon. This is a separator in Perl (as it is sometimes in a bash script) and this means that you can omit the final semi-colon in a code-block, but this is considered bad practice and it can be a source of errors if additional code is added.</p>
<h2 class="sectiontitle">Counting Lines in a File</h2>
<p>This is a slightly more complex program, as shown in figure 2.</p>
<pre class="inset">
1. #!/usr/bin/perl
2. # A short perl program to count the lines in a file
3.
4. use 5.16.3;
5. use warnings;
6.
7. # use a scalar variable for the name of the file
8. my $filename = "linesfile.txt";
9.
10. open(FH, $filename); # open the file
11. my @lines = &lt;FH&gt;; # read the file
12. close(FH); # close the file
13.
14. my $count = scalar @lines; # the number of lines in the file
15. say "There are $count lines in $filename";</pre>
<p class="caption">Figure 2 - A short perl program to count the lines in a file, part 1</p>
<p>On line 8, we are declaring a variable using the keyword my and this declares the variable to be lexically scoped within the enclosing code-block or file.</p>
<p>The variable name, $filename, has a $ sign at the front which indicates that this is a scalar variable (that is, it holds a single value at a time as opposed to an array, for instance, which can hold as many values as is required). Perl supports three types of variable, scalar, array and hash.</p>
<p>A value can be a string, floating-point number or an integer and Perl will automatically convert between these types. This can be referred to as Duck typing, if it looks like a string it’s probably a string.</p>
<p>Just as a $ sign declares a variable to be scalar, an @ sign declares it to be an array and we can see this in line 11. In line 10, we have opened the file with filename, linesfile.txt and in line 11, we have assigned the contents of the file to an array called lines (which actually is a reflection of the fact that the file is read as a series of lines).</p>
<p>Line 12 closes the file. Note that although we have represented the filename with the variable name, $filename, it is important to remember that this represents the name of the file, not the file itself. The actual file is represented by FH.</p>
<p>Line 14 is interesting. We have a scalar variable called $count and we are giving this the value scalar @lines. When you take the scalar value of the array, it returns a single value and this is the size of the array.</p>
<p>Line 15 outputs the number of lines to the screen.</p>
<h2 class="sectiontitle">Loops and Conditionals</h2>
<p>Again, we are increasing the complexity of the code. We are doing this with a more complex version of the line counting program we saw in the previous section. For instance, this version of the program includes some basic error checking.</p>
<pre class="inset">
1. #!/usr/bin/perl
2. # A short perl program to count the lines in a file, part 2
3.
4. use 5.16.3;
5. use warnings;
6. use IO::File;
7.
8. my $filename = "linesfile.txt"; # the name of the file;
9.
10. # open the file with simple error reporting
11. my $fh = IO::File-&gt;new( $filename, "r" );
12. if(! $fh) {
13. print("Cannot open $filename ($!)\n");
14. exit;
15. }
16.
17. # Count the lines
18. my $count = 0;
19. while( $fh-&gt;getline ) {
20. $count++;
21. }
22.
23. # close and print
24. $fh-&gt;close;
25. print("There are $count lines in $filename\n");</pre>
<p class="caption">Figure 3 - A short perl program to count the lines in a file, part 2</p>
<p>In line 6, we have use IO::File;. This reads on the IO file module which is an object-oriented file-handling library (I’m not sure if this is just Perl syntax, but it looks like this may be a class so if we were looking for an equivalent in Java, it is probably the use of extends to inherit from a class rather than the import statement for adding a library).</p>
<p>In line 11, we are creating an object using this ‘library’ and we have stored this in the scalar variable $fh.</p>
<p>Line 12 is simply testing whether the file was opened successfully in which case (! $fh) would evaluate to false. That is, $fh evaluates to true if the file was opened successfully therefore (! $fh) evaluates to false. As a result, if the file fails to open (meaning that (! $fh) has evaluated to true), the error message is displayed and the program terminates (with the exit; command).</p>
<p>Line 12 is simply testing whether the file was opened successfully in which case (! $fh) would evaluate to false. That is, $fh evaluates to true if the file was opened successfully therefore (! $fh) evaluates to false. As a result, if the file fails to open (meaning that (! $fh) has evaluated to true), the error message is displayed and the program terminates (with the exit; command).</p>
<p>Assuming the file has opened successfully, the while loop then executes. Note the condition here, while( $fh-&gt;getline ). Essentially, this means that while we can successfully retrieve a line from the file, the loop will continue and the counter will increment on each iteration. The getline function is also part of the IO::File ‘library’.</p>
<p>Another significant difference between this version and the previous version is that this time, we are reading in one line at a time from the file. In the previous version, we read in the whole file as an array and simply returned the size of the array. For a small file, such as linesfile.txt, the earlier version may be a bit more efficient but doesn’t scale very well. By reading in one line to memory at a time, we can use this method to count much larger files then the previous version would be able to handle.</p>
<p>When the while loop is finished, we close the file and display the result. Actually, closing the file can be considered to be optional because the file is automatically closed when the program exits from the code block it belongs to. In this example, this would mean that the file would be closed when we exit from the program.</p>
<h2 class="sectiontitle">Functions</h2>
<p>Both versions of the code that count lines of text have been very straightforward and not too dissimilar from code in other languages such as C or Java. In this section, we are starting to see more Perl syntax and a little more complexity.</p>
<pre class="inset">
1. #!/usr/bin/perl
2. ## countlines3.pl by Bill Weinman &lt;http://bw.org/contact/&gt;
3.
4. use 5.16.0;
5. use warnings;
6. use IO::File;
7.
8. main(@ARGV);
9.
10. ## entry point
11. sub main
12. {
13. my $filename = shift || "linesfile.txt";
14. my $count = countlines( $filename );
15. say "There are $count lines in $filename";
16. }
17.
18. # countlines ( filename ) - count the lines in a file
19. # returns the number of lines
20. sub countlines
21. {
22. my $filename = shift;
23. error("countlines: missing filename") unless $filename;
24.
25. # open the file
26. my $fh = IO::File-&gt;new( $filename, "r" ) or
27. error("Cannot open $filename ($!)\n");
28.
29. # count the lines
30. my $count = 0;
31. $count++ while( $fh-&gt;getline );
32.
33. $fh-&gt;close;
34.
35. # return the result
36. return $count;
37. }
38.
39. # error ( string ) - display an error message and exit
40. sub error
41. {
42. my $e = shift || 'unkown error';
43. say "$0: $e";
44. exit 0;
45. } </pre>
<p class="caption">Figure 4 - A short perl program to count the lines in a file, part 3</p>
<p>The code in figure 4 demonstrates some of the basic principles of using functions in Perl. Note that in Perl, functions are generally referred to as subroutines, so a function is declared with the keyword, sub.</p>
<p>Unlike languages such as C or Java, Perl does not require a main function and does not start execution by looking for a function called main. In fact, it executes by simply taking the lines in the file in sequential order so we can see that after the use statements, there is one line of code which is line 8 and everything else is wrapped up in subroutines.</p>
<p>In terms of sequential execution, the code within the subroutines is ignored until a call is made to that subroutine. So, in this example, the line of code calls a subroutine, main but we could equally have taken the lines from the main subroutine and placed them where we have the call to main. We could also have called the main subroutine something else and it would have worked just as well.</p>
<p>However, in this case, there is an advantage to having a main function which is then called in this way. Note that the call to main in line 8 also passes it an array, (@ARGV). Actually, this array represents the parameters passed to the program from the command line. Having a main function therefore makes it easier to deal with these parameters since we can pass the entire array (note that @ARGV is a predefined Perl array) over to the function that we defined.</p>
<p>You will recall that when we called the previous versions of the countlines script, we did not pass it any parameters. But the third version, as we will see in a bit more detail later, is designed to work with a parameter. Normal execution would be something like</p>
<p class="inset">$ ./countlines3.pl filename</p>
<p>To illustrate this, let’s say we create a new file called linesfile2.txt which has 40 lines. If we pass this as a parameter to either the first or second version of the script, we will see that the output is</p>
<p class="inset">There are 50 lines of text in linesfile.txt</p>
<p>If we pass it as a parameter to the version of the script shown in figure 4, the output we see is</p>
<p class="inset">There are 40 lines of text in linesfile2.txt</p>
<p>The earlier versions of the script are not processing any parameters they receive so if we do pass one in, it is ignored.</p>
<p>Now, inside the main function, we have line 13</p>
<p class="inset">my $filename = shift || "linesfile.txt";</p>
<p>This is a simple bit of error checking. We have a scalar variable, $filename and an expression shift || "linesfile.txt". We are setting the value of $filename to the result of this expression. We read from the array with the shift function so if a filename has been passed as a parameter, shift will return that and this becomes the value of $filename.</p>
<p>If there is no parameter passed, the second part of the expression is evaluated and this returns the string "linesfile.txt", which becomes the value of $filename. This is actually a common technique of optionally passing a parameter and it makes use of the fact that the or expression only evaluates the second part if the first part fails to return a value.</p>
<p>The next line of code (line 14) calls the countlines function and passes it $filename as a parameter. The value that this returns is assigned to the variable $count. This is then output in the say statement on line 15.</p>
<p>Now, let’s take a look at the countlines() function. It starts with the line</p>
<p class="inset">my $filename = shift;</p>
<p>which again is taking the value of the parameter which is read in with the shift function and this value is assigned to the variable, $filename. In this function, we are not going to set the filename to something else if there is no parameter. However, the next line will do a bit of error checking.</p>
<p class="inset">error("countlines: missing filename") unless $filename;</p>
<p>This is a different kind of conditional, a post-fix conditional, which essential says, here is an error message to be displayed unless filename has a value.</p>
<p>Next, we have another conditional statement.</p>
<pre class="inset">
1. my $fh = IO::File-&gt;new( $filename, "r" ) or
2. error("Cannot open $filename ($!)\n");</pre>
<p>Note that we are using IO::File again and we have a different type of or statement and we will go into the difference between the two later. Here, we are either going to successfully open the file or print the error message.</p>
<p>The loop that does the actual counting is a while loop.</p>
<pre class="inset">
1. # count the lines
2. my $count = 0;
3. $count++ while( $fh-&gt;getline );
4.
5. $fh-&gt;close;</pre>
<p>Again, we have a post-fix operator here, we are saying increment count while reading lines so it is very readable and easy to understand and it only increments the count if a valid line is returned. When this is no longer the case, the loop terminates and the file is closed.</p>
<p>Note that although this is a simple and powerful technique, it is only suitable for simple loops like this where we have a single line of code in the loop.</p>
<p class="bolder">The sample code is missing the last part of the code so that needs to be added – this is the function that displays an error message.</p>
<p>The last bit of code is there to display an error message if one is encountered. It makes use of a couple of built-in variables, $0 and $e. To see this in action, we can force an error by not passing the program a parameter, assuming there is no file with the default name or pass it a dummy name for a non-existent file.</p>
<p>$0 gives us the path name for the script (including the filename for the script) and $e gives us the error message.</p>
<h2 class="sectiontitle">Using Perldoc</h2>
<p>Perl has a built-in documentation system but it is also available on the web which is probably more convenient. This can be found at <a href="https://perldoc.perl.org/">https://perldoc.perl.org/</a>.</p>
<p>For example, let’s say we want to find out about a module, we can search for this using the same sort of syntax we would use to declare it in a program such as IO::File. If we use this as a search term, this will return the relevant info. Actually, this doesn’t seem to be a recognised search term in the current version on the web but an alternative that does work is to select the Modules drop down in the top right corner and then select I and scroll down to IO::File.</p>
<p>If we want information on a function such as say or print, we can use the search box or similar to the above, select the drop down for Functions then S or P and select the function from the alphabetical list.</p>
<p>Assuming we have a fully installed version of Perl, we can also access Perldoc through the command line so, using the same examples, we could type</p>
<p class="inset">$ perldoc IO::File</p>
<p>We can also get information on a function like this but we need to use the –f option so for print this would be</p>
<p class="inset">$ perldoc –f print</p>
<p>It looks as though the same information is displayed whichever method you use to find it.</p>
<p>This information is produce using the POD (Plain Old Documentation) documentation system included with Perlpod. It’s easy to use and you can get more info on it by searching for perlpod in the online documentation or with</p>
<p class="inset">$ perldoc perlpod</p>
<p>at the command line. Familiarity with perldoc and perlpod is recommended!</p>
<br><br>
</article>
<div class="btngroup">
<button class="button" onclick="window.location.href='basic.html';">
Next Chapter - Basic Syntax
</button>
<button class="button" onclick="window.location.href='perl5essentialtraining.html'">
Course Contents
</button>
<button class="button" onclick="window.location.href='/programming/programming.html'">
Programming Page
</button>
<button class="button" onclick="window.location.href='/index.html'">
Home
</button>
</div>
</body>
</html>