You are the visitor number
since February 1, 1996 to
look at my Information Age project page at
EST.
How to read this tutorial Perl project?
#!/bin/perl (or the path Perl located on your system) Some may have: #!/usr/local/bin/perl your program : : :With this line, the shell knows where to look for Perl to run the program.
#!/bin/perl print "Say Hi to Neon!";
'hello' # 5 characters 'don\'t' # 5 characters 'hello\n' # 7 characters
Escape | Meaning --------+------------------------------------------ \n | Newline \r | Return \t | Tab \f | Formfeed \b | Backspace \v | Verticle tab \a | Bell \e | Escape \cC | CTRL + C \\ | Backslash \" | Double quote \l | Lowercase next letter \L | Lowercase all following letters until \E \u | Uppercase next letter \U | Uppercase all following letters until \E \E | Terminate \L or \UAnother feature of double-quoted strings is that they are variable interpolated. That means that some variable names within the string are replaced by their current values when the strings are used.
Comparison | Numeric | String ------------------------+---------------+--------------- Equal | == | eq Not Equal | != | ne Less Than | < | lt Greater Than | > | gt Less than or Equal To | <= | le Greater Than or Equal To| >= | ge ------------------------+---------------+---------------
$a = 5; # assign 5 to $a $b = 4; # assign 4 to $b $c = $a * $b; # assign 20 to $c $d = "Hello, World"; # assign a string to $d
$a = $a + 2; # Without the Binary Assignment Operator $a += 2; # With the Binary Assignment Operator
$a +=1; # With the Binary Assignment Operator $a++; # With Postfix Autoincrement $++a; # With Prefix Autoincrement $b = 3; $c = $b++; # $b is 4 and $c is 3 after this expression $d = ++$b; # both $b and $d are 5 after this expressionSame to Autodecrement.
$s = "Hello"; chop($s); # $s becomes "Hell"It is useful when you read a value from < STDIN >. You can use chop() operator to remove the newline character which may cause problems in the future.
$a = "zoo"; $b = "elephants"; $c = "We can see $b in the $a."; # $c is "We can see elephants in the zoo." now
An array is an ordered list of scalar data. Each element of the
array is a separate scalar variable with the corresponding value.
@test1 = ("Hello", "World");# It has 2 elements now. @test2 = @test1; # test2 is the same as test1. @test3 = (@test1,"pal"); # test3 is ("Hello","World","pal") ($t1, $t2) = (6, 12); # assign 6 to $t1, 12 to $t2 ($t1, $t2) = ($t2, $t1); # swap $t1 and $t2 @test = (1, 2, 3); @test = (0, @test); # @test is now (0, 1, 2, 3) @test = (@test, 4); # @test is now (0, 1, 2, 3, 4) ($tmp, @test) = @test; # @test is now (1, 2, 3, 4), $tmp is 0 $length = @test; # $length is 4 now ($length) = @test; # $length is 1 now(the first element of @test)
@test = (1, 2, 3); $t1 = @test[2]; # $t1 is 3 now $test[1] = 6; # @test is (1, 6, 3) now $test[0]++; # @test is (2, 6, 3) now $test[0] *= 5; # @test is (10, 6, 3) now
@test = (1, 3, 5); push(@test, 2, 4, 6); # @test is (1, 3, 5, 2, 4, 6) now $last = pop(@test); # @test is (1, 3, 5, 2, 4) and $last is 6 nowBoth push() and pop() will take an array variable name as the first argument.
unshift(@test, 7, 8); # @test is (7, 8, 1, 3, 5, 2, 4) $first = shift(@test); # @test is (8, 1, 3, 5, 2, 4) and $first is 7
@test1 = (1, 2, 3); @test2 = reverse(@test1); # @btest2 is (3, 2, 1)However, @test1 is unchanged. reverse() works on a copy not the original one. If you want to reverse the array, do the following:
@test1 = reverse(@test1);
@test1 = (10, 5, 3, 7, 47, 8); @test2 = sort(@test1); # @test2 is (10, 3, 47, 5, 7, 8)Again, if you want to change the original list, do the following:
@test1 = sort(@test1);
One thing we have to notice is that there is no particular order for the elements of an associative array. Whenever we want to find some specific values, we use the keys to find them. We do not have to worry how we can find them because Perl has the internal order to do this.
Most of time, people want to access the elements of the associative array rather the entire array. At this time, we need the keys to do this. The associative array is represented as:
%testand an element of an associative array is represented as:
$test{$key} # Notice! The leading character is a dollar sign($) and so is the key.How do we create and/or update an associative array? Here are some examples:
$test{1} = "Hello"; # creates key 1 and value "Hello" $test{2} = 100; # creates key 2 and value 100We can also assign the key-value pairs to a list array.
@test1 = %test; # @test1 is either (1, "Hello", 2, 100) or (2, 100, 1, "Hello")The order of the key-value pair is arbitrary and cannot be controlled. Perl has its own logic to have more efficient access. Of course, the list array can copy its values to an associative array.
%test2 = @test1; # %test2 is just like %test now.
@test3 = keys(%test); # @test3 is either (1, 2) or (2, 1)
@test4 = values(%test); # @test4 is either ("Hello", 100) or (100, "Hello")
$personinfo{"011-88-6257"} = "John"; $personinfo{"323-56-2943"} = "Tom"; $personinfo{"242-54-2489"} = "Sam"; print "SSN \t\t NAME\n"; print "----------------------\n"; while ( ($ssn, $name) = each(%personinfo) ) { print "$ssn \t $name\n"; } The result looks like: SSN NAME ---------------------- 242-54-2489 Sam 011-88-6257 John 323-56-2943 TomAs mentioned above, the order of key-value pair is arbitrary. In this case, we can see the result. We created the associative array by "John --> Tom --> Sam" but got "Sam --> John --> Tom".
We borrowed the while() statement that we will discuss later on in the section of control structures.
print %personinfo,"\n"; delete $personinfo{"011-88-6257"}; print %personinfo,"\n"; The resule looks like: SSN NAME ---------------------- 242-54-2489 Sam 011-88-6257 John 323-56-2943 Tom 242-54-2489Sam011-88-6257John323-56-2943Tom 242-54-2489Sam323-56-2943Tom
There are several statements provided by Perl.
if (expression) { statement 1; statement 2; : : } else { statement a; statement b; : : }One thing we have to know is that the control expression is evaluated for a string value. That means, there will be no change if it is already a string but it will be converted to a string if it is a number.
On the other hand, if you want to do the reverse way, you can apply unless instead of if statement. The meaning of unless statement is "If the expression is not true, then ...".
You can also apply elsif as many times as you wish to expand your if/else statement.
if (expression 1) { : : } elsif (expression 2) { : : } else { : : }
while (expression) { statement 1; statement 2; : : }We will execute the statements inside the brackets if the expression is true via while statement. However, we may want to do the other way. Instead of true value of the expression, we can let until statement test the false value and do the execution.
until (expression) { statement 1; statement 2; : : }
for (initial_exp; test_exp; increment_exp) { statement 1; statement 2; : : }
foreach $s (@list) { statement 1; statement 2; : : }
$test1 = < STDIN >; @test2 = < STDIN >;The first one reads a value from the standard input terminated with a newline character. The second one reads as many lines as you want to until you press "CTRL+D" to terminate it.
print "Hello, World.\n"; print 123+456;
$name = "John"; $age = 23; $ssn = "121-66-3214"; printf "My name is %10s. I am %3d years old. My SSN is %11s.", $name, $age, $ssn; The resule looks like: My name is John. I am 23 years old. My SSN is 121-66-3214.
Perl also provides the notion of a simple report template which is called format. A format in Perl contains two parts: constant part (the column header, labels, fixed text, ...) and variable aprt (current data).
Using a foramt consists of doing three things:
Usually, the first step is done once and the other two are done repeatedly.
format formatname = fieldline value_1, value_2, value_3 fieldline value_4, value_5 .Here comes an example for an address label:
format ADDRESSLABEL = ============================= @<<<<<<<<<<<<<<<<<<<<<<<<<<<< $name @<<<<<<<<<<<<<<<<<<<<<<<<<<<< $address @<<<<<<<<<<<<, @< @<<<<<<<<<< $city, $state, $zipcode ============================= .
$name = "John Starks"; $address = "1234 Erie Blvd."; $city = "Syracuse"; $state = "NY"; $zipcode = "13205"; write ADDRESSLABEL; The resule looks like: ============================= John Starks 1234 Erie Blvd. Syracuse, NY 13205 =============================
Similarly, we can have right-justified field by @>>>> and centered field by @||||.
format ACCOUNT = Deposit: @#####.## Withdraw: @#####.## Balance: @#####.## $deposit, $withdraw, $deposit-$withdraw .
format TEST = ===================== @* $test ===================== . $test = "test1\ntest2\ntest3\ntest4\n"; write; Then, we will get the result: ===================== test1 test2 test3 test4 =====================
format ADDRESSLABEL_TOP = Address label page @< $% .The ($%) is used to display the page number. As a matter of fact, this variable is the number of times the top-of-page format has been called for a particular file handle.
In Perl, we can speak of the string test as a regular expression by enclosing the string in slashes.
while (<>) { if (/test/) print "$_"; }What if we are not sure how many e's between "t" and "s"? We can do the following:
while (<>) { if (/te*st/) print "$_"; }This means "t" is followed by zero or more e's and then followed by "s" and "t".
We, now, introduce a simple regular expression operator -- substitute. It replaces the part of a string that matches the regular expression with another string. It looks like the s command in sed, consisting the letter s, a slash, a regular expression, a slash, a replacement string and a final slash, looks like:
s /te*st/result/;Here, again, the $_ variable is compared with the regular expression. If they are matched, the part of the string is replaced by the replacement string ("result"). Otherwise, nothing happens.
A pattern-matching character class is represented by a pair of open and close square brackets, and a list of characters inside. If you want to put some special characters like ], -, ..., you need to use backslash(\). There is a shorter expression of a long and consecutive list of numbers or characters. Use a dash(-) to represent.
[0123456789] # all digits [0-9] # the same with above [0-9\]] # all digits and right square bracket [a-z0-9] # all lowercase letters and digits [a-zA-Z0-9_] # all letters and digits and underscoreThere is another negated character class which is reverse to the character class. It leads by a caret(^) character right after the left square bracket. This negated character class matches any single character that is not in the list. For example:
[^0-9] # match any single non-digit [^aeiouAEIOU] # match any single non-vowel [^\]] # match any character except a right square bracketSome readers might think, it is bothersome to type so many characters everytime. Is there an abbreviation for digits and/or characters? The answer is "Yes". Perl provides some predefined character classes for your convenience.
Construct | Equivalent Class | Negated Construct | Equivalent Negated Class -----------+------------------+-------------------+------------------------- \d (digits)| [0-9] | \D (non-digits) | [^0-9] \w (words) | [a-zA-Z0-9_] | \W (non-words) | [^a-zA-Z0-9_] \s (space) | [\f\n\r\t] | \S (non-space) | [^\f\n\r\t]
We may, sometimes, need to specify the number of characters we want to handle. We, therefore, need the concept of general multiplier. The general multiplier consists of a pair of matching curly braces with one or two numbers inside. The format will look like:
/a{3,8}/ # must be found 3 a's to 8 a's /a{3,}/ # means 3 or more a's /a{3}/ # exactly 3 a's /x{0,3}/ # 3 or less a'sNow, let's think about those 3 grouping patterns mentioned before. "*" is jukst like {0,}, "+" is just like {1,} and "?" is like {0,1}.
Another grouping pattern operator is a pair of open and close parentheses around any part pattern.
/a(.)b\1/; # It can be matched by "axbx"What if there are more than one pair of parentheses in the regular expression? If this is the case, the second pair of parentheses is referenced as \2, and so on.
/a(.)b(.)c\1d\2/; # It can be matched by "axbycxdy"Another usage is in the replacement string of a substitute command.
$_ = "a xxx b yyy c zzz d"; s/b(.*)c/s\1t/; # $_ becomes "a xxx s yyy t zzz d".Another grouping pattern is alternation in form of a | b | c. It can also be used for multiple characters. As a matter of fact, it is better to use a character class for single character alternatives.
/sony|panasonic/; # match either sony or panasonicHere are some more examples of regular expressions, and the effect of parentheses:
abc* # abc, abcc, abccc and so on (abc)* # abc, abcabc, abcabcabc and so on ^a|b # a at the beginning of a line or b anywhere ^(a|b) # either a or b at the beginning of a line (a|b)(c|d) # ac, ad, bc, or bd (red|blue)pen # redpen or bluepen
$test = "Good morning!"; $test =~ /o*/; # true $test =~ /^Go+/; # also trueOne thing we have to notice again here is we never store the input into a variable. That means, if you want to match this input again, you won't be able to do so. However, this happens often.
< STDIN > =~ /^y/i; # accepts both "Y" and "y"
$tmp =~ /\/etc\/fstab/;As we know, if we want to include slash characters in the regular expression, we need to use a backslash in front of each slash character. It looks funny and unclear. Perl allows you to specify a different delimiter character. Precede any nonalphanumeric character with an "m".
m@/etc/fstab@ # using @ as a delimiter m#/etc/fstab# # using # as a delimiter
$_ = "God bless you."; /bless/; # $` is God " now # $& is "bless" now # $' is " you." now
$_ = "feet feel sleep"; s/ee/oo/g; # $_ becomes "foot fool sloop"You can also use a scalar variable as a replacement string.
$_ = "Say Hi to Neon!"; $new = "Hello"; s/Hi/$new/; # $_ becomes "Say Hello to Neon!"You can also specify an alternate target with the =~ operator.
$test = "This is a book."; $test =~ s/book/desk/; # $test becomes "This is a desk."
$test1 = "This is a project for CPS600."; @test2 = split(/\s+/,$test1); # split $test1 by using " " as delimiter # @test2 is ("This","is","a","project","for","CPS600.")If we change $test1 to be $_, we can have shorter code. Since /\s+/ is the default pattern.
$_ = "This is a project for CPS600."; @test2 = split; # same as @test2 = split(/\s+/,$_)
$test1 = join(/ /, @test2);We can have the original $test1 by the join() operator. One thing we have to notice is the glue string is not a regular expression, it is just an ordinary string of zero or more characters.
We have seen some system functions such as print, split, join, sort, reverse, and so on. Let's take a look at user defined functions.
sub subname { statement 1; statement 2; statement 3; statement 4; : : : }The subname is the name of the subroutine. It can be any name. The statements inside the block are the definitions of the subroutine. When a subroutine is called, the block of statements are executed and any return value is returned to the caller. Subroutine definitions can be put anywhere in the program. They will be skipped on execution. Subroutine definitions are global, there are no local subroutines. If you happen to have two subroutine definitions with the same name, the latter one will overwrite the former one without warning.
&say_hi; sub say_hi { print "Say Hi to Neon!"; }The result of this call will display "Say Hi to Neon!" on screen.
A subroutine can call another subroutine, and that subroutine can call another and so on until no memory left.
$a = 5; $b = 5; $c = &sumab; # $c is 10 $d = 5 + &sumab; # $d is 15 sub sumab { $a + $b; }A subroutine can also return a list of values when evaluated in an array context.
$a = 3; $b = 8; @c = &listab; # @c is (3, 8) sub listab { ($a, $b); }The last expression evaluated means the last expression which is evaluated rather than the last expression defined in the subroutine. In the following example, the subroutine will return $a if $a > $b, otherwise, return $b.
sub choose_older { if ($a > $b) { print "Choose a\n"; $a; } else { print "Choose b\n"; $b; } }
&say_hi_to("Neon"); # display "Say Hi to Neon!" print &sum(3,8); # display 11 $test = &sum(4,9); # $test is 13 sub say_hi_to { print "Say Hi to $_[0]!\n"; } sub sum { $_[0] + $_[1]; }Excess parameters are ignored.
What if we want to add all of the elements in the list? Here is the example:
print &sum(1,2,3,4,5); # display 15 print &sum(1,3,5,7,9); # display 25 print &sum(1..10); # display 55 since 1..10 is expanded sub sum { $total = 0; foreach $_ (@_) { $total += $_; } $total; # last expression wvaluated }
sub sum { local($total); # let $total be a local variable $total = 0; foreach $_ (@_) { $total += $_; } $total; # last expression wvaluated }When the first body statement is executed, any current value of the global value $total is saved away and a new variable $total is created with an undef value. When the subroutine exits, Perl discards the local variable and restores the previous global value.
sub larger_than { local($n, @list); ($n, @list) = @_; local(@result); foreach $_ (@list) { if ($_ > $n) { push(@result, $_); } } @result; } @test1 = &larger_than(25, 24, 43, 18, 27, 36); # @test1 gets (43,27,36) @test2 = &larger_than(12, 22, 33, 44, 11, 55, 3, 8); # @test2 gets (22,33,44,55)We can also combine the first two lines of the above subroutine.
local($n, @list) = @_;This is, however, a common Perl like style. Here is a tip about the using of the local() operator. Try to put all of your local() operators at the beginning of the subroutine definition before you get into the main body of the subroutine.
open(FILEHANDLE,"filename"); # open a file for reading open(FILEHANDLE,">outputfile"); # open a file for writing open(FILEHANDLE,">>appendfile"); # open a file for appending
close(FILEHANDLE);
open(FILEHANDLE,"test") || die "Sorry! Cannot open the file "test".\n";
open(FILE1,$test1) || die "Cannot open $test1 for reading"; open(FILE2,">$test2") || die "Cannot create $b"; while (< FILE1 >) { # read a line from file $test1 to $_ print FILE2 $_; # write the line into file $test2 } close(FILE1); close(FILE2);
File Test | Meaning ----------+-------------------------------------------------- -r | File or directory is readable -w | File or directory is writable -x | File or directory is executable -o | File or directory is owned by user -R | File or directory is readable by real user -W | File or directory is writable by real user -X | File or directory is executable by real user -O | File or directory is owned by real user -e | File or directory exists -z | File exists and has zero size -s | File or directory exists and has nonzero size -f | Entry is a plain file -d | Entry is a directory -l | Entry is a symlink -S | Entry is a socket -p | Entry is a named pipe (a "fifo") -b | Entry is a block-special file (a mountable disk) -c | Entry is a character-special file (an I/O device) -u | File or directory is setuid -g | File or directory is setgid -k | File or directory has the sticky bit set -t | isatty() on the filehandle is true -T | File is "Text" -B | File is "Binary" -M | Modification age in days -A | Access age in days -C | Inode-modification age in daysYou can check a list of filenames to see if they exist by the following method:
foreach (@list_of_filenames) { print "$_ exists\n" if -e # same as -e $_ }
unlink("test"); # delete the file "test" unlink("test1","test2"); # delete 2 files "test1" and "test2" unlink(< *.ps >); # delete all .ps files like "rm *.ps" in the shell You can also provide the selection from the users. print "Input the filename you want to delete: "; chop($filename = < STDIN >); unlink($filename);
$old = "test1"; $new = "test2"; rename($old, $new); # "test1" is changed to "test2"
When you invoke ls -l on the directory containing a symbolic link, you get an indication of both the name of the symbolic link and where the link points. Perl provides the same information by using readlink().
mkdir("test", 0755); # It generates a directory called "test" and its permission is "drwxr-xr-x"You can use a rmdir(directory_name) to remove the directory just like rmdir directory_name in the shell.
chmod(0644,"test1"); # change the permission of "test1" to be "-rw-r--r--" chmod(0644,"test1","test2");# change the permission of both files to be "-rw-r--r--"
Assume "test"'s UID is 1234 and its GID is 56. chown(1234, 56, "test1", "test2"); # make test1 and test2 belong to test and its default group.
One of the great things of Perl is that there are some programs converting from different languages to Perl.
$a2p < awkprog > perlprogNow, you can have the Perl program(script) ready to run.
There exist Perl4 and Perl5. What's the difference between them? Basically, they are two different versions of the language. Perl5 has been modularized, object oriented, tweaked, trimmed, and optimized.
There are some new features shown in Perl5:
You can check the following WWW sites for more information:
![]() |
|||
---|---|---|---|
Name | Chang-An Hsiao (Andrew) | ||
chsiao@nj37bf3s.bns.att.com | |||
Address | 613 Center Street Apt#104 | ||
Herndon | VA | 22070-5010 | |
Phone Number | Home | Work | Fax |
(703)742-4080 | (703)713-2894 | (703)713-2597 |