View
215
Download
0
Embed Size (px)
Citation preview
Perl
File I/O and Arrays
File I/O
• Perl allows to open a file to read, write, or append
• As well as pipe input or output to another program. —We get to this piping later on
• Command• open (FILEHANDLE, "filename"); #read a file• open (FILEHANDLE, "<filename");# same• open (FILEHANDLE, ">filename");# write to
file• open (FILEHANDLE, ">>filename"); #append
Filehandles
• <STDIN>, <STDOUT>, and <STDERR> are filehandles that are built into perl.
• The style is to write a filehandle as all caps.
• Example:open (FP, "filename");#open filename for reading, referenced by
FP• open returns a true/false value
—false if it failed to open the file.
What to do if the file fails to open
• Since open returns a value, we can write statements like this
open FP, $file or die "Can 't open: $file $! \n";open FP, $file or warn "Can't open: $file $! \n";
—$! is the error message.—warn prints the string as a warning message.—die exits the program and prints a string.
• A more readable versionunless (open(FP, $file) ) {
die "Can't open $file: $! \n";}
• If you have multiple files to process in sequence
FILE: foreach $file (@arrayoffilesnames) { unless (open FP, $file) {
warn "Can't open $file: $! \n";next FILE;
} # statements;
}
Reading from an open file• Once the file is open, the Filehandle uses the
same syntax as <STDIN>open FP, "file";$line = <FP>;• When accessing a file you need <> around the
filehandle• End of File marker
—Perl makes it very easy to read until the EOF
while( $line = <FP>) {chomp($line); # remove the EOL marker.
#process input}• It exits the loop on the end of file.
—Actually the file handle returns undef, which is a false value.
closing the file
• use the close command—close (filehandle);
– () are optional in both close and open statements.
• complete example of reading a file
unless (open FP, $file) { die "Can't open $file: $! \n";}
while ($line = <FP>) {chomp($line);#process file
}close FP;
File I/O Example
• Moving the chomp function
unless (open FP, $file) { die "Can't open $file: $! \n";}
while (chomp($line = <FP>)) {—Note the chomp in the read—Also works for <STDIN>
#process file}close FP;
Exercise 3
• Using the grading script from last time—Change it to read from a file and print the
grades to the screen.
• You will need to create a file and don't need a sentinel value.
Output to a file
• Using either write or append. • unless (open FO, ">file") {die "can't open file $!\
n";}
• You need to add the file handle to output statements
• Exampleprint FO "Hello world!\n";
—Note: No comma after the file handle for the print statement.
printf(FO, "Hello world!\n");—printf follows standard c format for the file
handle
Open Statement and Pipes
• You can "open" and executable program and pipe the output into the perl script for processing
• open FP, "executable program |";• Everything functions just as if you opened
a file to read.
open statement and pipes (2)
• Exampleopen FP, "ls -la |";while (chomp($line = <FP>)) {
# process a directory list}close FP;
open statement and pipes (3)
• Also use it to direct input to another file• open FP, "| someprogram";print FP, "input to file";
• open FP, "| someprogram|";—Not legal, an error will be generated. —In the networking lecture, we'll look at two
way pipes.
Arrays
• Perl has arrays and hashing (called associative arrays) built in.
• The rest of this lecture will focus on arrays
• To "declare" an array—my @arr;
Array syntax
• Like c/c++ syntax—$arr[0] = 1; —But you can't use $arr++;
– without the [], perl assumes it is a scalar variable.
• The @ vs the $.• In most cases the $ is used when
accessing arrays, so—$arr[0] = 12;—A general rule of thumb, when accessing a
slice of an array, use $— when referring to the entire array, use @
Arrays
• like all perl variables, arrays are type less—$arr[0] = 1; $arr[1] = "Jim";
• And they can be as many dimensions as needed.—$arr[0][0] =1; $arr[0][1] = "Jim";
• Since you can't declare how big an array is, perl allows you to uses as many slices as needed.—The cell is only allocated in memory when you use it—So $arr[0] =1; $arr[1000] =2;
– Uses only two spots in memory, instead of 1000
—The indices cannot be negative on assignments.– $arr[-20] = 3; # maybe syntax error. * See slide on
indices
—Unused spots, return "" as a result, so– print $arr[50]; #prints nothing.
the Whole array
• Initializing an array@stuff = ("one", "two", "three");
—Like, c, the first element is the 0 index—print "$stuff[0]"; # prints one
• Copying one array to another@x = @stuff;• Creating arrays from other arrays and
scalar data@x = (@stuff, @x, "hi",1,$z); #note the ( )
—First index of the array is 0
multidimensional arrays
• two-dim arrays initializing• @2D = ( [1,2,3], [4,5,6], [7,8,9]);
—$2d[1][1] contains 5
• @x = ([@stuff], [@x], ["Hi"], [$z]);—$x[2][0] contains "hi"
Length of an array
• Two methods—Uses $#arrayname—$x = $#stuff; #$x contains 2,
– There are 3 items, but index of the third item is 2
• OR—$x = @stuff;
– May think this would give you the top element (as in stacks, we'll get arrays as stacks later)
—$x contains 3, ie there are three items in the array.
• Note the $# vs the @• Also
—$s[0] =1; $s[1]; $s[40];—$x = @stuff; #$x contains 41! it's for consistency—$x = $#stuff; #$x contains 40;
Length of an array (2)
• 2D (or more) array lengths@arr = ([1,2],[1,2,3],[1,2,3,4]); #2D arrayprint $#arr; output: 2 works only the first
Dim
• We use indirection (pointers) to find the length for the 2nd Dimension.
print $#{$arr[0]}; #output 1print $#{$arr[2]}; #output 3• Butprint @arr[0]; output: ARRAY(0x8281023)
—Which is the pointer to the array.
Does the value exists?
• $s[0] =1; $s[1]; $s[40];—There is no value for $s[2 .. 39]
• You may want to check and see if a value exists
• use exists operator. Returns true if the value exists, otherwise false.—exists doesn't care if the value is true or false,
only that there is a value.—defined operator works the same.
if (exists $s[1] ) { print $s[1]; }if ($s[1]) { print $s[1]; }
—This prints only when the value of $s[1] is true. But slice may exist, but have false value
array indices
• Negative indices (bad idea, you shouldn't use them)
@arr = (1,2,3);print $arr[-1]; # prints 3• A negative index, start from the end of the
array, but be careful, you will produce an error, if you try and access a slice below Zero.
• The indices cannot be negative on assignments—Not completely true.
• So $x[-1] = 1; #syntax error, if the memory has not be allocated or index is below zero.
• But $arr[-1] = 4; #changes $arr[2] to 4
using arrays as stacks and queues
• push array, LIST—push LIST onto the end of the array—push @arr, 1;—push @arr, (1, 2, 3);
– same as @arr = (@arr, (1,2,3));
• pop array—removes the last element of the array—$v = pop @arr;
• shift array—shifts of the first value of the array.—$v = shift @arr;
• unshift array, LIST—shifts LIST onto the front of the array—unshift @arr, 0;
using arrays as stacks and queues (2)• as a stack
—push items on the array, the pop them back off—example:push @a, 1; push @a, 2; push @a, 3;$v = pop @a; # $v contains 3$v = pop @a; # $v contains 2$v = pop @a; # $v contains 1$v = pop @a; # $v contains ""
• as a queue—push items on, then shift them off—push @a, (1,2,3);—$v = shift @a; #$v contains 1—$v = shift @a; #$v contains 2—$v = shift @a; #$v contains 3—$v = shift @a; #v contains ""
Exercise 4
• Again, use the grading program from exercise 3.—This time also put each grade value into an
array—After you have finished reading the file
– go through the array, find the min, max, and the average grade.
– print out this information.
—Think about which control structure allows you go process the array and how to get each value into the array.
More on creating lists
• Comma's are optional in some conditions@releases = qw( alpha beta gamma);• qw commands Quotes the Words
—Also the () don't have to parentheses. You can use [], <>, //, {}, etc.
—Some people prefer to use [], instead ().
• @a = qw(a b c d);—$a[0] = "a"; $a[1] = "b"; $a[2] = "c"; $a[3] =
"d";
lists in general
• Like lisp, ( … ) denotes a list. • And can include variables:
($a, $b, $c, $d) = ("Jim", "Sam", "Greg", $f);—$a contains "Jim", $b contains "Sam", etc.—This is important for later use.
• () is a null list. ((),(),()) is the same as ()• perl treats lists as arrays.$a = (1,2,3)[1]; # $a = 2
—again useful later, when functions return arrays, but we only want a slice of it.
lists in general (2)
• $x = ( ($a, $b, $c) = ( 1,2,3));—$x contains 3, $a has 1, $b has 2, etc.
• $x = ( ($a, $b) = ( 1,2,3));—$x contains 3, not 2, $a has 1, $b has 2, the 3
is lost.
• $x = ( () = ( 1,2,3));—$x still contains 3, and the values are lost.
• Remember ( ) is treated as an array, so $x will have the array (list) length.
More on arrays
• Clearing arrays• Either
—@stuff = (); —set it equal to the empty list
• OR—$#stuff = -1; —Change the array length to empty.
• But does not clear the memory allocated to the array.
• use this commandundef(@stuff);
—deallocates memory and clears the array
more on arrays (2)
• ranges in array, same as in loops@a = $stuff[2 .. 4];
— copy only slice 2, 3, and 4 into @a
@a = $stuff[2,4,6];— copy only slice 2, 4, and 6 into @a
@a = $stuff[0, 2 .. 4];— copy only slice 0, 2,3,4 into @a
($v1,$v2,$v3) = $stuff[0,2,3];— copy slice 0 into $v1, slice 2 into $v2, etc.
functions for arrays (lists)
• sort—defaults to sort based on string value
ascending—array = sort array@x = sort @y
• reverse—returns a list of elements in the opposite order@x = reverse @y;
—sorting in descending order@x = reverse sort @y;
More on sort
• User defined sorting with sort—create a subroutine for sorting—We'll look at subroutines later
– the sort subroutines are a special case.
—Sort numerically, instead of by string valuesub numerically { $a <=> $b }@x = sort numerically @y;
—sort case insensitivelysub strcaseinsensitive { lc($a) cmp lc($b) }@x = sort strcaseinsensitive @y;
– lc function returns a lower case value
More on sort (2)
— The subroutine can be written inline as well@x = sort {$b <=> $a} @y
• cmp (string compare) and <=> (numerical compare) return -1, 0, or 1 if the left side is greater, they are the same, or the right side is greater, respectively.— NOTE: $a and $b are part of the sort package
and do not effect your variables.
• You can also define sort routines to sort hashed and complex variables. As well as very complex sorting.— See the perldoc for more examples.
foreach and arrays
• Since an array is just a list, we can use the foreach statement.
@stuff = ("one", "two", "three");foreach $val (@stuff) {
print $val, "\n";}output:onetwothree• The loop terminates, at the "end" of the
array.
foreach and arrays (2)
• Using the indices
foreach $i (0 .. $#stuff) { print "$stuff[$i] \n";}• or only the range you wantforeach $i (0, 2 .. $#stuff) {
– If the array is shorter than 2, it will stop.
print "$stuff[$i] \n";}
interpolation of arrays to a string (1)
• print will printout the values of 1 dimensional
print "@arr \n";—prints values with a single space between them
• It doesn't matter what precedes or follows the array, still prints the same
print @arr, "\n";—print the array with no space between
print "@2Darray";—prints the pointers to the arrays, instead of
values
interpolation of arrays to a string (2)
• $str = "@arr";—produces a string of the elements, separated
by a space.
• $str = "@2Darray";—same as printing, the string has the pointers.
• $str = "$2Darray[0]";—produces a string with the pointer to slice 0
• $str = "@{$2Darray[0]}";—produces a string of values from the that
section.—To get all the values into one stringforeach $i (0 .. $#2Darray) {
$str .= "@{$2Darray[$i]} ";}
Input and arrays
• Remember that <STDIN> reads until the end of a line (same of file I/O)
• Unlike c/c++ and most languages, perl reads the entire line into a variable.
• So $x = <STDIN>; #gets the whole line• chomp($x); #get rid of the end of line
marker.
Now what?
We need to split that string up into useful parts.
split operator
• using the split operator. split(' ',$x);• splits up a string into parts. We want to
split up the string on the space and creates a list.
• @stuff = split(' ',$x); #puts the list into the array.—Now we have the input as would be expected.—The value it splits on is removed.—Example:$x = "Hi there, 1";@stuff = split(' ', $x);—$stuff[0] = "Hi", $stuff[1]="there,", $stuff[2]=1;
split (2)
• Or a string can be split into scalar variables
($v1, $v2, $v2) = split(' ',$x);• $v1 ="Hi"; $v2="there,"; $v3=1;• Definition of split( ) = split ( what to split on, variable);
—split ' ', $x; works as well. Also () and the variable are optional.
—Be careful to use the correct " and '
@stuff = split('e, ', $x); —$stuff[0] = "Hi ther"; $stuff[1]=1;
split (3)
• If you only wanted the second part(undef,$v1) = split('e, ', $x);
—$v1 = 1; undef says to throw it away.
• splitting scalar and arrays($v, @stuff) = split(' ',$x);
—$v = "Hi", @stuff has the rest;
(@stuff, $v) = split(' ',$x);—$v = 1; @stuff has the first part.
join operator
• join takes a list and creates a single string• string = join "string to be added between
parts", LIST
$str = join ' ',@stuff;—$str = "Hi there, 1";
$str = join "stuff", ("Buy ", "Fun ");—$str = "Buy stuff Fun ";
join operator (2)
• Html example with join• Create a table with arrays in htmlprint "<table><tr><td>\n";$str = join "</td><td>", @arrayofvalues;print $str, "\n";print "</td></tr></table>\n";• output:<table><tr><td>val</td><td>val</td><td>val</td></tr></table>
Exercise 5
• Write a script that reads a line of numbers.—From a file or STDIN—loop until you get to the end of the file
– for STDIN on windows use control-z– for STDIN on UNIX use control-d
• For each line—It should add them up all the values.—It should print:
– sum = the sorted listed of numbers in descending order.
QA&