Link | Description | Commands Used |
Lists and Array Variables | Relation between lists and Array Variables | array list @A = (i, j, k); |
Access Array Elements | Array Subscripts and Scalar Variables | $A[i], -n<=i<=n |
Brackets | Brackets with Array Variables | ${array}[0] $array\[0] $array" . "[0] |
List Range Operator | Using the List range operator with Array Variables | (a..z); |
Copying Arrays | Making a copy of an Array | @A2 = @A1 = (1, 2, 3); |
Assigning Scalars | Assigning Scalar variables from Array Elements | ($1, $v2, $v3) = @A; |
List extents | List Length and List Maximum Subscript | Length: $v = @A; Max Subscript: $v = $#A; |
Array Slices | Extracting subsets of Array Elements | @slice = @A[1,2,3]; |
Slice Ranges | List Range operator in Array Slices | @A[0..4] means @A[0,1,2,3,4] |
Overlapping Slices | Using Array slices on either side of = | @A[1, 2] = @A[2, 3]; |
Slice Notation | Slice Notation possibilities | @A[1, 2] = @A[2, 1]; |
Reading <STDIN> | Arrays and <STDIN> | @A = <STDIN>; |
Functions | Functions used with Arrays | sort(), reverse(), chop(), chomp(), join(), split() |
Debugging 1 | Debugging Exercise | |
File System Access | Opening, processing and closing files | open(), close(), die() |
File Test Operators | File Test Operator list | form: -x expression |
Global Variables | Global Variables for output | $, $\ $" |
31. Lists and Array Variables o A list is a sequence of scalar values enclosed in parentheses. e.g. (1, 5.3, "hello", 2) contains 4 elements, each of which is a scalar value. The empty list is denoted (). Note that 43.2 and (43.2) are different: the first is a scalar and the 2nd is a list. o A scalar variable, $var, can always be included as part of the list. Suppose $var = 26, then the list (17, $var, "string") is evaluated as (17,26,"string"). o The value of an expression can also be an element of a list. (17, $var<<2) becomes (17, 104). (17, $var1+$var2) becomes (17, 0) when $var1 = -26. oString Substitution: Since Character strings are scalar values, they can be used in lists and scalar variable names may be substituted for in character strings in lists. ($var, "The answer is $var") becomes (26, The answer is 26) o You may store lists in special variables called array variables. @array = (1,2,3); {@ is the designation for the array variable.} variable naming:@ then 2nd character is a letter, others are letters, digits or underscore. all other characters are illegal. legal array variable names: illegal array variable names @my_array @1array @list2 @_array @a_very_long_name @a.new.array o Note that scalar variable names ($var) are in a different name space than array variables (@var). 32. Accessing Array Variable elements: o Use subscripts (zero based) to access array variable elements: $scalar = $array[0]; # first element of array called array # Note: $array[0] is a scalar, hence $ not @ @array = (1, 2, 3, 4); $array[3] = 5; print ("array values are: " @array); # output is: array values are: 1 2 3 5 o The Rule: Things that reference one value (scalar variables and array elements) must start with a $. o @array = (1, 2, 3, 4); $scalar1 = $array[4]; $scalar2 = $array[-1]; # last element is assigned print ($scalar1, "\t"); print ($scalar2); # output is null string for each: 4 o There is no bounds checking: @array = (1, 2, 3, 4); $index = 4; $scalar = $array[$index] # output is null definition of scalar and no error message. 33. Examples: $ cat program12.perl #! /usr/bin/perl # a program that prints the elements of a list @array = (1, "Chicken", 1.23, "\"Having fun?\"", 9.33e+23); $count = 1; while ( $count <= 5 ) { print ("Element $count is $array[$count-1]\n"); $count++; } $ program12.perl Element 1 is 1 Element 2 is Chicken Element 3 is 1.23 Element 4 is "Having fun?" Element 5 is 0.3300000000000005+e23 $ cat program13.perl #! /usr/bin/perl # a program that generates random integers between 1 and 10 # produce the random numbers and save $count = 1; while ( $count <= 100) { $randnum = int ( rand(10) ) + 1; #rand outputs floating values # between 0 and 1; then # multiplies it by 10. int # truncates the result to be 0-9 $randtotal[$randnum] += 1; # $randtotal is initially "" then # converted to 0 to get updated # by 1 $count++; } # output the total of each number $count = 1; print ("Total for each number: \n"); while ( $count <= 10 ) { print ("\t number $count: $randtotal[$count]\n"); $count++; } $ program13.perl Total for each number: number 1: 11 number 2: 8 number 3: 13 number 4: 6 number 5: 10 number 6: 9 number 7: 12 number 8: 11 number 9: 11 number 10: 9 34. Using Brackets as Brackets with arrays When both @array and $array are defined and you wish to print $array[0] and not the array's first element, then specify: "${array}[0]" "$array\[0]" or "$array" . "[0]" context is array \[ not 1st element . is concatenation operator Note that "$\{var}" contains the text ${var} explicitly 35. The List Range Operator .. o (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) is equivalent to (1..10) using the list range operator .. Other usages: (1, 5..7, 10) becomes (1, 5, 6, 7, 10) (2.1..5.3) becomes (2.1, 3.1, 4.1, 5.1) (4.5..1.6) becomes () since ascending order of operands required (3..3) becomes (3) $var1 = 7; $ var2 = 4; ($var1..$var2+5) becomes (7,8,9) o Example: $ cat program14.perl #!/usr/bin/perl # A program that uses list ranges to print a list of numbers print ("Enter the starting number:\n"); $start = <STDIN>; chop($start); print ("Enter the ending number:\n"); $end = <STDIN>; chop($end); @list = ($start..$end); $count=0; print ("Here is the list:\n"); while ($list[$count] != 0 || $list[$count-1] == -1 || $list[$count+1] == 1) { print ("$list[$count]\n"); $count++; } $ program14.perl Enter the starting number: -2 Enter the ending number: 2 Here is the list: -2 -1 0 1 2 35. Copying arrays The list stored in @array1 is copied to the array variable @array2. Each element of the 1st array is the same as the corresponding element of the 2nd array. @array2 = @array1 # @array1 elements already defined @array2 = @array1 = (1, 2, 3); @list1 = (2, 3, 4); @list2 = (1, @list1, 5); # meaning (1, 2, 3, 4, 5) $ cat program 15.perl #!/usr/bin/perl # A program that assigns a list as part of another list @lotus = (1, 2, 3); @innerlist = " never "; @outerlist = ("I", @innerlist, "fail!\n"); print (@outerlist "\n"); print (@lotus "\n"); print ("@lotus", "\n"); # print "@lotus"; also works without () $ program 15.perl I never fail! 123 1 2 3 36. Assigning Scalars from Array variables $var1=7; $var2=5; @array = ($var1, $var2); ($var3, $var4, $var5) = @array; print ("$var3", "$var5", "$var4"); # output is: 7 5 and $var5 is null string ($var3, $var4) = (7, 5, 3); # assigns multiple scalar variables via a list # the third element of the list, 3, remains unassigned. 37. Retrieving the length of a list @array = (7, 5, 1); $scalar = @array; #output is the number of elements or length (3) of a list. Note that the following have different effects: $scalar = @array; # $scalar = 3 ($scalar) = @array; # ($scalar) = (7) $scalar = (7, 5, 1); # $scalar = 1 3 scalars separated by comma op. # so $scalar = 7, then = 5, finally = 1) Another Note: You can get the highest subscript of an array using the following notation: @a = (1,2,3); $#a will output the subscript of the highest element of array @a This is the same as the total number of elements of the array minus one, since 0 based subscripting is used. For Example: $ perl -e '@a = (1, 2, 3); $a[6] = 7; $c = @a; $b = $#a; print "$c $b \n";' 7 6 Example: Print the contents of an array @array = (a..z); $i = 0; while ($I <= $#array) { print $array[$i++], "\n"; } If you deliberately modify the value of $#array to be: larger than actual: implies the added elements are all undefined; smaller than actual implies that the truncated elements are discarded; Scalar Context - The Rule: For $numelements = @arrayname; The left side has a scalar variable, so the assignment is operating in a scalar context thus the array representing the list evaluates to the number of elements in the array, a single value. Boolean Context - The Rule: Lists that have any elements, including undefined elements, are considered true in a Boolean Context. An empty list is considered false. Scalars in a Boolean context are true if non-zero and false if zero, null, or undefined. Functions and Parentheses - The Rule. Functions also operate with their arguments evaluated in context. If you supply a parenthesized set of arguments to that function, the evaluation is straightforward based on the argument given. If you supply a comma separated set of arguments, without parentheses, Perl builds a list from those arguments. But which is safer? print 4 + 5, 6, 'foo'; print (4 + 5), 6, 'foo'; print ((4 + 5), 6, 'foo'); o The scalar() function To force a list to be evaluated in a scalar context, use the scalar function. Compare: print @num; print scalar(@num); The print statement evaluates its arguments in a list context by default. $ cat program16.perl #!/usr/bin/perl # A program that prints every element of an array @array = (14, "cheeseburger", 1.23, -7 "I give up"); $count = 1; while ($count <= @array) { # @array means its length print ("Element $count: $array[$count - 1]\n"); $count++; } $ program16.perl Element 1: 14 Element 2: cheeseburger Element 3: 1.23 Element 4: -7 Element 5: I give up 38. Using Array Slices @array = (7, 5, 3); $array[3] = 1; @subarray = @array[2,3]; # 3rd, 4th elements of @array # @array[2,3] is an array slice @slice = @array[1,2,3]; # array assignment references get @ $slice = $array[0]; # scalar assignment references get $ $ cat program17.perl #!/usr/bin/perl # A program that prints every element of an array @array = (14, "cheeseburger", 1.23, -7 "I give up"); @subarray = @array[1,2]; print ("The first element of subarray is $subarray[0]\n"); print ("The 2nd element of subarray is $subarray[1]\n"); $ program17.perl The first element of subarray is cheeseburger The 2nd element of subarray is 1.23 39. Using list ranges in Array Slice subscripts @array[0, 1, 2, 3, 4] can be written as @array[0..4] using .. when $endrange = 4; @subarray = @array[0..$endrange]; # variables work in subscripts $ cat program18.perl #!/usr/bin/perl # A program that uses an array variable as an array slice subscript @array = (14, "cheeseburger", 1.23, -7 "I give up", 0); @range = (1, 2, 3); @subarray = @array(@range); print ("The array slice is @subarray\n"); # "@subarray" -> contents # @subarray -> concatenated contents $ program18.perl The array slice is cheeseburger 1.23 -7 You can assign to array slices via: @array[0,1] = ("string", 46); @array[0..3] = (1, 2, 3, 4); $beginrange = 0; $endrange = 5; @array[$beginrange..$endrange] = (1, 2, 3, 4); # @array[5] = "" $endrange = 2; @array[$beginrange..$endrange] = (1, 2, 3, 4); # last list item ignored $ cat program19.perl #!/usr/bin/perl # A program that assigns to an array slice @array = ("old1", "old2", "old3", "old4"); @array[1,2] = ("new1", "new2"); print ("The array contents is @array\n"); $ program19.perl The array contents is old1 new1 new2 old4 40. Overlapping Array Slices You can use array slices on either side of an assignment statement @newarray = @array[2, 3, 4]; @array[2, 3, 4] = @newarray; This allows array slices to be assigned to each other, even if they overlap. @array[1, 2, 3] = @array[2, 3, 4]; # since the list is stored in # memory during the assignment e.g. @array = ("one", "two", "three", "four", "five"); @array[1, 2, 3] = @array[2, 3, 4]; print ("@array\n"); # output is: one three four five five Note that mismatched lengths are handled as above (empty ignorance) e.g. @array[0..2] = @array[3, 4]; The value of the array is now: ("four", "five", "", "four", "five") 41. Array Slice notation In perl, there is no difference between an array slice and a list containing consecutive elements of the same array. Thus @subarray = @array[0, 1]; @subarray = ($array[0], $array[1]); So you can refer to any elements of an array in any order. e.g.: @subarray = ($array[4], $array[1], $array[3]); @subarray = @array[4, 1, 3]; @subarray = @array[0, 0, 0]; # yeilds first element 3 times @array[1, 2] = @array[2, 1]; # swap elements 2 and 3 $ cat program20.perl #!/usr/bin/perl # A program that sorts an array print ("Enter the array to sort, one item at a time.\n"); print ("Enter an empty line to quit.\n"); $count = 1; $inputline = <STDIN>; chop ($inputline); while ( $inputline ne "" ) { @array[$count-1] = $inputline; $count++; $inputline = <STDIN>; chop ($inputline); } # Do the sorting $count = 1; while ( $count < @array ) { $x = 1; while ( $x < @array ) { if ($array[$x-1] gt $array[$x]) { @array[$x-1,$x] = @array[$x,$x-1]; } $x++; } $count++; } print ("@array\n"); $ program20.perl Enter the array to sort, one item at a time. Enter an empty line to quit. foo baz dip bar sty bar baz dip foo sty A one liner using the sort function: @array2 = sort(@array); # This sorts (strings) alphabetically in ascending order. 42. Reading an Array from <STDIN> $ cat program21.perl #!/usr/bin/perl # A program that reads data into an array and writes that array @array = <STDIN>; print (@array); $ program21.perl This is line 1 This is the second line This is the last line <Ctrl-D> This is line 1 This is the second line This is the last line $ 43. Array Library functions o sort Sorting a list or Array variable sortedlist = sort ( array ); # array and sortedlist are both arrays. @array = ("this", "is", "a", "sentence"); @array2 = sort (@array); print ("@array2"); # @array2 contains the sorted list: ("a", "is", "sentence", "this") # output is the sorted list: a is sentence this sort (@array); # doesn't do anything because it is not assigned @array = (70, 100, 8); @array2 = sort (@array); # @array2 contains (100, 70, 8) in ascii order The sort() function for ascii ascending ordered sorts uses the explicit ordering: sort { $a cmp $b} @asciiarray; # same as sort @asciiarray For numerical ascending sorts, use the explicit ordering: sort { $a <=> $b} @numarray; o reverse Reverses the order of elements of a list or array variable reversedlist = reverse ( array ); # array and reversedlist are both arrays. $ cat program22.perl #!/usr/bin/perl # A program that sorts in reverse order @input = <STDIN>; @input = reverse ( sort (@input)); # alternatively: @input = reverse sort (@input); is permitted print (@input); $ program22.perl foo bar dip baz sty <Ctrl-D> sty foo dip baz bar $ o chop and chomp revisited chop removes the last character of each element of a list and returns that character. @list = ("rabbit", "12345", "quartz"); chop (@list); # @list now contains ("rabbi", "1234", "quart") Use chop on arrays generated from <STDIN> chomp removes the line endings (newlines) from all elements of a list and returns the number of such removals. @list = ("rabbit", "12345", "quartz"); chomp(@list) # @list is unchanged chomp doesn't tamper with the character strings like chop does. Use chomp on arrays generated from <STDIN> or not. o join creates a simple string from a list of strings, which can then be assigned to a scalar variable. string = join (array); string is a character string; array is a list (1st element of array is "field" separator for the rest). $string = join (" ", "this", "is", "a", "character", "string"); # $string contains: this is a character string @list = ("here", "is", "a"); $string = join (" ", @list, "string"); # $string contains: here is a string $ cat program23.perl #!/usr/bin/perl # A program that converts an array to a string using join @input=<STDIN>; chop (@input); # or chomp (@input); $string = join (" ", @input); print ("$string\n"); $ program23.perl This is my input <Ctrl-D> This is my input $ o split creates an array or a list from a character string array = split (/pattern/, string); string is a character string; array is a list; pattern matches the "field" separator in the string). $string = "words::separated::by::colons"; @array = split ( /::/, $string ); # @array contains the list: ("words", "separated", "by", "colons") $ cat program24.perl #!/usr/bin/perl # A program that does a simple word count $wordcount = 0; @line=<STDIN>; while ( $line ne "" ) { chop($line); # or chomp ($line); @array = split(/ +/, $line); # + is a reg exp character # matches 1 or more of previous # character. $wordcount += @array; $line = <STDIN> } print ("Total number of words: $wordcount\n"); $ program24.perl Here is some input. Here are some more words. Here is my last line. <Ctrl-D> Total number of words is 14 $ cat program25.perl #!/usr/bin/perl # A program that reverses the word order of the input file @input = <STDIN>; chop(@input); # First reverse the order of words on each line $currline = 1; while ( $currline <= @input ) { @words = split (/[ \.\!\?]+/, $input[$currline-1] ); @words = reverse (@words); $input[$currline-1] = join(" ", @words, "\n"); $currline++; } # Now reverse the order of the input lines and print them @input = reverse (@input); print (@input); $ program25.perl This sentence is in reverse order. <Ctrl-D> order reverse in is sentence This $ 44. Debugging Corner: What's wrong here? $result = @array[4]; ---------------------------------- #!/usr/bin/perl @input = <STDIN>; $currline = 1; while ( $currline < @input ) { @words = split(/ /, $input[$currline]); @words = sort (@words); $input[$currline] = join (" ", @words); $currline++; } print (@input); ----------------------------------- #! /usr/bin/perl print 'Enter list of numbers: '; chomp($in = <STDIN>); @nums = split(" ", $in); @sorted = sort @nums; print "Numbers: @sorted\n"; $totalnums = $#nums; print "Total number of numbers: $totalnums\n"; 45. Perl and the File system: Opening files o open To access a file exclusively open ( filevar, filename ); where filevar is the variable name that perl uses to refer to the file (aka file handle) and filename represents the location in the filesystem of this file. open returns a success or failure status value filevar is named by a letter followed by letters, digits, or underscore. No reserved words allowed. By convention, use uppercase letters to distinguish file variables from other variable names and reserved words. open (FILE1, "file1"); # relative path specification open (FILE1, "/home/faculty/katz/file1"); # full path specification # tells perl that it should open the file, file1 (in the current directory) and associate it with the file variable FILE1 open can work with three modes: read, write (overwrite) and append. open(FILE1, "file1"); # opens for reading open(FILE1, ">file1"); # opens for writing open(FILE1, ">>file1"); # opens for appending Before using an open file, make sure the open succeeded. if open returns a non-zero value, the file has been opened successfully (Boolean Success) if open returns a zero value, an error has occurred. test via: if ( open(MYFILE, "/home/faculty/katz/myfile") ) { # what to do if file opened successfully } o Reading from a file $ cat program26.perl if ( open(MYFILE, "/home/faculty/katz/myfile") ) { $line = <MYFILE>; while ( $line ne "" ) { print ($line); $line = <MYFILE>; } } $ program26.perl line 1 line 2 line 3 $ o die Terminating a program and sending a message to STDERR die (message); The program terminates immediately and an (error) message is printed. $ cat program27.perl #! /usr/bin/perl # exercising the right to die unless ( open(MYFILE, "/home/faculty/katz/myotherfile") ) { die ("Cannot open input file '/home/faculty/katz/myotherfile'\n"); } #unless ( open(MYFILE, "/home/faculty/katz/myotherfile") ) { # die ("Missing input file"); #} $line = <MYFILE>; while ( $line ne "" ) { print ($line); $line = <MYFILE>; } } $ program27.perl Cannot open input file '/home/faculty/katz/myotherfile' # Missing input file at program27.perl line 2 o Reading into Array Variables @array = <MYFILE> #entire file contents stored in @array # one line per element o Writing to a File open (OUTFILE, ">outfile"); print OUTFILE ("Here is an output line.\n"); $ cat program28.perl #! /usr/bin/perl # a program which copies one file to another unless (open(INFILE, "file1") ) { die ("Cannot open file 'file1'\n"); } unless (open(OUTFILE, "file2") ) { die ("Cannot open output file 'file2'\n"); } $line = <INFILE>; while ($line ne "") { print OUTFILE ($line); $line = <INFILE>; } $ program28.perl $ o Merging (Shuffling) two files $ cat program29.perl #! /usr/bin/perl # a program which merges two files with interleaved lines open(INFILE1, "file1") || die ("Cannot open file 'file1'\n"); open(INFILE2, "file2") || die ("Cannot open file 'file2'\n"); print STDERR ("File 'file1' and 'file2' opened successfully.\n") $line1 = <INFILE1>; $line2 = <INFILE2>; while ($line1 ne "" || $line2 ne "" ) { if ( $line1 ne "" ) { print ($line1); $line1 = <INFILE1>; } if ( $line2 ne "" ) { print ($line2); $line1 = <INFILE2>; } } $ program29.perl File 'file1' and 'file2' opened successfully. a1 b1 a2 b2 a3 b3 a4 $ o Closing files (Done automatically at end of program) close (filevar); File variable filevar indicates what file is being closed. open (MYFILE, ">file1"); print MYFILE ("Here is line 1.\n"); # to file1 open (MYFILE, ">file2"); # MYFILE is closed automatically first print MYFILE ("Here is another line1.\n"); # to file2 close (MYFILE); #MYFILE is closed explicitly 46. File Test Operators -x expr where x is an alphabetic character; expr is an expression -b Is expr a block device? Non-zero status if true -c Is expr a character device? -d Is expr a directory? -e Does expr exist? -f Is expr an ordinary file? -g Does expr have setgid bit set? -k Does expr have its sticky bit set? -l Is expr a symbolic link? -o Is expr owned by user? -p Is expr a named pipe? -r Is expr a readable file? -s Is expr a non-empty file? -t Does expr represent a terminal? -u Does expr have setuid bit set? -w Is expr a writable file? -x Is expr an executable file? -z Is expr an empty file? -A How long since expr accessed? -B Is expr a binary file? -C How long since expr's inode accessed? -M How long since expr modified? -O Is expr owned by the real user only? (logged in user) -R Is expr readable by the real user only? -S Is expr a socket? -T Is expr a text file? -W Is expr writeable by the real user only? -X Is expr executable by the real user only? $ cat program30.perl #! /usr/bin/perl # a program tests for file existence before writing to it open(INFILE, "file1") || die ("Cannot open file 'file1'\n"); if ( -e "outfile") { die ("Output file outfile already exists.\n"); } open(OUTFILE, "file2") || die ("Cannot open file 'file2'\n"); # # Alternatively: #open (INFILE, "file1") && !( -e "outfile") && # open(OUTFILE, ">outfile") || die("Cannot open file\n"); $line = <INFILE> while ($line ne "") { chop ($line); print OUTFILE ("\U$line\E\n"); $line = <INFILE>; } $ program30.perl $ 47. Output Global Variables Three Global variables affect how lists can be output. $, This variable, null by default, is the Output field separator. It contains the characters to print inbetween list elements. $\ This variable, null by default, is the Output record (line) separator. It contains characters to print at the end of a list. $" This variable, single space by default, is like the Output record separator. However, it specifically affects list variables interpolated inside strings. Printing bare lists: $ perl -e 'print(1,2,3);' 123$ $ perl -e '$, = "*"; $\ = "\n"; print (1,2,3);' 1*2*3 $ perl -e '$" = "#"; $\ = "\n"; $, = " "; @var = (a,b,c,d,e); print (0,"ABC@{var}DEF",1);' 0 ABCa#b#c#d#eDEF 1
Questions? Robert Katz: katz@cis.highline.ctc.edu