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,, and 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 { 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 open FP, "file"; $line = ; 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 = ) { 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 = ) { 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 = )) { —Note the chomp in the read —Also works for #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 = )) { # 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
Array syntax Like c/c++ syntax —$arr[0] = 1; —But you can't use $arr++; –without the [], perl assumes it is a scalar variable. 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,
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 = ("one", "two", "three"); —Like, c, the first element is the 0 index —print "$stuff[0]"; # prints one Copying one array to Creating arrays from other arrays and scalar "hi",1,$z); #note the ( ) —First index of the array is 0
multidimensional arrays two-dim arrays = ( [1,2,3], [4,5,6], [7,8,9]); —$2d[1][1] contains = ["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 –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 Also —$s[0] =1; $s[1]; $s[40]; —$x #$x contains 41! it's for consistency —$x = $#stuff; #$x contains 40;
Length of an array (2) 2D (or more) array = ([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 2 nd Dimension. print $#{$arr[0]}; #output 1 print $#{$arr[2]}; #output 3 But output: ARRAY(0x ) —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 = (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 1; (1, 2, 3); –same = (1,2,3)); pop array —removes the last element of the array —$v = shift array —shifts of the first value of the array. —$v = unshift array, LIST —shifts LIST onto the front of the array 0;
using arrays as stacks and queues (2) as a stack —push items on the array, the pop them back off —example: 1; 2; 3; $v = # $v contains 3 $v = # $v contains 2 $v = # $v contains 1 $v = # $v contains "" as a queue —push items on, then shift them off (1,2,3); —$v = #$v contains 1 —$v = #$v contains 2 —$v = #$v contains 3 —$v = #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 = 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 = 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 = (); —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 —deallocates memory and clears the array
more on arrays (2) ranges in array, same as in = $stuff[2.. 4]; —copy only slice 2, 3, and = $stuff[2,4,6]; —copy only slice 2, 4, and = $stuff[0, 2.. 4]; —copy only slice 0, 2,3,4 ($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 = reverse —returns a list of elements in the opposite = —sorting in descending = reverse
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 = sort —sort case insensitively sub strcaseinsensitive { lc($a) cmp lc($b) = sort –lc function returns a lower case value
More on sort (2) —The subroutine can be written inline as = sort {$b 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 = ("one", "two", "three"); foreach $val { 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 \n"; —prints values with a single space between them It doesn't matter what precedes or follows the array, still prints the same "\n"; —print the array with no space between print —prints the pointers to the arrays, instead of values
interpolation of arrays to a string (2) $str = —produces a string of the elements, separated by a space. $str = —same as printing, the string has the pointers. $str = "$2Darray[0]"; —produces a string with the pointer to slice 0 $str = —produces a string of values from the that section. —To get all the values into one string foreach $i (0.. $#2Darray) { $str.= "; }
Input and arrays Remember that 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 = ; #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 = 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, = 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 = 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 = split(' ',$x); —$v = has the rest; $v) = split(' ',$x); —$v = 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 ' —$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 html print " \n"; $str = join " print $str, "\n"; print " \n"; output: val val val
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 &