450 likes | 636 Views
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
E N D
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 version unless (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 • Example print 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) • Example open 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 array print $#arr; output: 2 works only the first Dim • We use indirection (pointers) to find the length for the 2nd Dimension. print $#{$arr[0]}; #output 1 print $#{$arr[2]}; #output 3 • But print @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 command undef(@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 value sub numerically { $a <=> $b } @x = sort numerically @y; • sort case insensitively sub 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: one two three • 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 want foreach $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 string foreach $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, $v3) = 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", “Now"); • $str = "Buy stuff Now";
join operator (2) • Html example with join • Create a table with arrays in html print "<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.
Q A &