perl note

$string=join(‘ ’,  (‘A’, ‘B’, ‘C’, ‘D’, ‘E’));The result would be $string set to “A B C D E”. (The parentheses around the arguments are optional as with most Perl functions.)

You can use the reverse function on a hash to reverse the pairs, converting the value to a hash key and the hash key to a value. This allows you to look up with either value:reverse %hash;

Reversing a hash swaps the hash key and value, not the order of the pairs in the hash
Be careful when using reverse.  Since all hash keys have to be unique, there is the chance of losing some data if the values are the same prior to reversing.
You can convert hashes to arrays and vice-versa easily, since they both have the same list structure. To convert, simply reassign using the proper variable name:%hash=(“A”, “B”, “C”, “D”);@array=%hash;%hash2=@array;
The first line creates a hash, the second converts the hash format to an array format, and the third line creates a new hash with the array’s contents.  

To remove all data from a hash (hash keys and values), you could use the delete function in a loop, but an easier way is to simply redefine the hash. Suppose you want to blank:%hash=(“A”, “B”, “C”, “D”);To blank this hash, just redefine it:%hash=();and the old values are deleted and a hash with no contents is left.

The grep function searches for patterns in an array. The syntax for Perl’s grep is:grep pattern, list;
For example, to find all the elements with the pattern “day” in the array:@days=qw(Monday, Tuesday, Friday);you would issue the command:@result=grep /day/, @days;which will populate the array @result with the matching elements.
Finding an intersection between @array1 and @array2 is surprisingly simple:%temp=();foreach (@array1){     $temp{$_}=1;}@intersect=grep $temp{$_}, @array2;
This code starts by setting up an empty hash. The foreach stores each element in @array1 in $_, one at a time, and fills the temp list with them and sets the values to 1 (so it is true). The last line examines @array2 one element at a time and sets it to $_, which is grepped in %temp. If there, it is an intersection element and added to @intersect.
Finding a difference is similar to an intersection but using negation:%temp=();foreach (@array1){     $temp{$_}=1;}@intersect=grep (! $temp{$_}, @array2);

Normally you will embed an open function inside an if statement to make sure the file was opened properly.  Otherwise, commands later in the program would cause errors.  Here’s a typical setup:if (open(BIGFILE, “datafile.dat”)){  statements to run }else{ print “Cannot open the file!\n”;  exit 0;}
After you have opened a file and done something with it, you should always close the file. Closing the file lets the operating system know the file is not in use anymore and the filehandle is freed.
To close a filehandle, use the close function with the handle name:open(BIGFILE, “data.txt”;statements…close BIGFILE;
There are a couple of ways to read from an open filehandle. The most common is to use the file input operator, which is a pair of angle brackets around the filehandle name (just like <STDIN> to read from the keyboard). For example:open(BIGFILE, “data.txt”) $line=<BIGFILE>;
This will read a line from the file data.txt (referred to by the filehandle and not the name) and store it in $line
The line $line=<MFILE>; will read a whole line of input from the MFILE filehandle. If there is nothing to read, the value “undef” (for undefined) is returned.
You can use loops to read through an entire file. To test whether the value undef has been detected, use the “defined” keyword: while (defined($line=<MFILE>)) …
Perl allows the code on the previous slide to be shortened. Instead of writing: while (defined($line=<MFILE>)) {print $line;}   you can write: while(<MFILE>) {print $_;}
This works because the shortform stores the line in the default variable $_. The shortform also checks for end-of-file for you.
So far, we read file contents into a scalar, one line at a time.  You could assign the lines read from a file to a list just as easily: open (MFILE, “data.txt”); @list=<MFILE>; close <MFILE>;
When using a list or array, the entire file is read in.  Each line in the file is assigned as one element in the list. (So the first line is @list[0], and so on.)
When an error is recorded by Perl, it stores the error number in a special variable called $!. When examined numerically, $! shows a number, but when examined as a string it shows an error message from the operating system. This can be used as part of the die string: die “Can’t open: $! \n”;
This statement will display the message “Can’t open” followed by the error string from the operating system when the die is triggered

Perl allows the UNIX file tests to be performed. This is usually done in a condition like this: if (-r FILE) {..}
The condition has one valid option followed by the filehandle to be tested. Alternatively, you can use a filename or full path and filename instead of a filehandle.
These tests are all UNIX tests available to Perl:
-B        true if a binary file
-d            true if directory
-e            true if file exists
-f            true if regular file
-M        returns age in days since last modification
-r             true if readable
-s            returns size of file in bytes
-T        true if text file
-w        true if writable
-z            true if file exists but is empty

Inside the subroutine, Perl uses the argument variable @_ to hold all the arguments. You can use @_ in your subroutines: sub showarg { print join(“ ”, @_);} showarg “This”,“is”,“a”,“test” ;
This program passes the four strings to showarg, which uses the join to paste them together with spaces between each one. The print displays the result.
The @_ variable is not related to the $_ variable
Inside a subroutine, each argument is accessed as a part of the @_ array using subscripts, as with any array. The first argument will be element @_[0], the second array element @_[1], and so on.
You can use loops to access each argument using the array element name

Inside a subroutine, using @_[x] can be awkward and counter-intuitive.  Perl allows you to name arguments being passed into the subroutine, just as with other language function arguments, but you have to do it by assigning the @_ array elements at the top of the subroutine code: sub foo1{ ($var1, $var2)=@_;  statements…}
This will assign the first argument to $var1, and the second to $var2, and so on if more are named
In the last section you passed scalars to a subroutine. Passing an array or hash to a subroutine is done in the same way: sub revarray  { return reverse(@_);} @rev=revarray @array;
This will pass the array @array to the subroutine revarray, reverse it, and store the result passed back from the subroutine into @rev.  The entire array is read in to the subroutine as @_.
You might think you could pass more than one array or hash in the same manner:  sub printarrays  { (@array1, @array2)=@_;   print @array1, @array2;} however this will not work as @_ will hold the two arrays together and there is no way to break them into two separate arrays in the subroutine.  There is no indication where one array ends and the next starts. In this case, @array1 would have the entire @_ contents and @array2 is empty.

To define a subroutine prototype, use the same syntax as when defining the subroutine itself. You do not have to specify variable names, but you can indicate the presence of variables by using the first symbol (such as $ or @) of the variable: sub mysub1 ($ $ $);
This defines a subroutine called mysub1 which will expect three scalars.  The actual code for mysub1 is defined later in the program.

If you have programmed in any other language that supports functions, you have seen scope.  Scope refers to the block of code where a variable has meaning.
If you define variables inside a Perl script they are available to any subroutines inside that script.  Variables created inside a subroutine are available outside the subroutine, as well (which is not how most programming languages behave). This is an important difference in language! In this case, the variables have scope in the entire program.

To help code reuse and portability, you want to be able to define variables inside a subroutine that have no meaning outside the subroutine.  This prevents conflicts with other script variables when you move the subroutine to new programs.  To define a local variable, you use the my operator:  my $var1; my @array1;
Any variable defined with the word my is considered private to the block of code it is defined in. That is where the variable has scope.

References are created exactly the same way as other variables, and have no special naming convention. To assign a value to the reference, you use the backslash: $refnum1=\$num1;
This will create a reference variable called $refnum1which will hold the memory address of the variable $num1. Creating a reference to a variable doesn’t affect the variable in any way.

To use the value a reference is pointing to, you have to tell the interpreter that you don’t want to know the memory address it holds, but the value inside the memory address it points to. This is done with the dereferencing operator. For example: print $refnum1; will print the memory address $refnum1 holds, but  print $$refnum1; will print the value in the memory address of $num1 (if that’s what it points to).
You can set up a reference to a reference, although you won’t need this type of ability until you get into complex coding: $num1=10; $refnum1=\$num1; $refnum2=\$refnum1; the last line sets $refnum2 to the value of $refnum1 (the memory location of $num1), and not to $num1 directly.  To dereference $refnum2 here and see the value of $num1, use: print $$$refnum2;
You can set up a reference to an array in the same way as a reference to a scalar.  Since the reference holds a memory address, it is a scalar itself and defined with a $: @array1=(“1”, “2”, “3”); $refarray1=\@array1;
The variable $refarray1 will have the memory address of the first element of the array @array1. It does not point to the entire array, just the start of the memory for @array1.
To dereference array references, you can reference any element in the array pointed to with the usual element subscript: $$refarray1[2]; This shows the value of the third element in whatever $refarray points to.
If you want to see the whole array, use: @$refarray1;
You can see a range of elements, too: @$refarray1[0-3]; shows the first four element in the array.
References to hashes are set up the same way as arrays: $refhash1=\%hash1;
You access single elements in the hash through the hash key, and get the value associated with that key back: $$refhash1{key};
To see the whole hash the reference points to, use: %$refhash1;
One of the strengths of references is the ability to pass references to arrays and hashes to subroutines. This allows more than one array or hash to be passed properly to a subroutine. Since the code:  sub twoarrays  { (@array1, @array2)=@_;…} does not work, as both arrays are joined into one array @_, references provide a way to pass scalars which reference more than one array.
To pass two arrays to a subroutine, you could do this: @array1=(…); @array2=(…); $refarray1=\@array1; $refarray2=\@array2; passarray($refarray1, $refarray2); sub passarray  { statements…} and both arrays can be used inside the passarray subroutine by dereferencing the references.


發佈了19 篇原創文章 · 獲贊 5 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章