####################################################### # # display-notes related to Intro to Perl, Class 5 # ####################################################### # last modified: 4-20-03, pre-class # today's topic - input/output basics (ref: "Learning Perl", ch. 6) * although, actually, it is really *more* input/output basics --- we've obviously been doing some of this already! 8-) #------------------------------------------------------------- more about STDIN * had we considered: returns undef when an end-of-file is reached; * so --- when you don't want to grab all the lines of input at once into an array (for memory/time considerations!), something like this could be useful: * (and note: "Learning Perl" notes that it *is* generally better to grab and process one-line-at-a-time instead of grabbing all the lines before processing --- see p. 88) while (defined($line = )) { # do what you wish to a $line known not to yet be end-of-file } * there's a lot going on in that first line! * next line of user input is read into $line when user types a carriage return/enter; * value of an assignment statement is (like C) the value assigned into the LHS --- so, for example, $looky = ($val = 8); * ...sets $looky to 8 ($val is set to 8, that makes 8 the value of the expression $val = 8, and so $looky is assigned to the value of that expression, 8.) * ...so, in line with above, argument of defined() call is whether ($line = ) assigns a value that is not undef to $line; * so, this is a handy construct --- ALTHOUGH note that we've got to be careful with chomp here! * what would this mean? while (defined(chomp($line = ))) * that's really asking if the value of the chomp() call is undefined! Not what you mean (esp. since it appears that chomp always returns a value --- 0 if a newline wasn't chomped off, 1 if it was; * see class5_01_chomp1 for experiment; while (chomp(defined($line = ))) * also no good --- defined returns true or false (likely in the form of some scalar value), chomp won't find a newline there, it'll return 0 --- and guess what while will do with that? * MORAL: when you do this, just gotta CHOMP separately (likely in the first line of the loop...) #-------------------------------------------------------------------- SHORTCUT for while (defined($line = )) * but --- given the warning about how it really is better to read and process 1 line at a time --- this is something that is potentially done a lot; is there a shortcut? while (defined($line = )) { # do what you wish to a $line known not to yet be end-of-file } * YES: Larry Wall chose some otherwise-useless syntax, and gave it a special meaning, to serve as a shortcut for this case; this means THE SAME as the above: while () { # do what you want to a line, stored in $_, known not to yet be # end-of-file } * (literally, this meant --- BEFORE Larry Wall changed it --- to read a line of input, see if it is true (which it normally is), enter loop if so, BUT throw away line read in!) * that was deemed useless enough to "replace" with this special meaning instead; * yes, this happens to store the value read in into the default variable $_ # 180class5_02_stdin1 -- example using 'while ()' * NOTE: this only works this way if is the ONLY thing in the conditional of a while loop (or a for loop)!! * note, too, that this is SUBTLY DIFFERENT: foreach () { print "I saw $_"; } * will you still see each line in output? yes; * BUT --- is in a LIST context, here! It is doing the warned-against reading of ALL input into an array before the loop can start running; * (and $_ is really acting as the default *loop control* variable, here;) * so, the 'while ()' is PREFERRED... #----------------------------------------------------------------------- the diamond operator <> * named by Larry Wall's daughter (cute footnote, Learning Perl, p. 88) * if you want a Perl program to act like a UNIX utility... * for example, in UNIX: cat dog cat * ...returns the lines of file dog then the lines of file cat more dog cat * ...displays the lines of file dog then the lines of file cat, but stopping after each screen and waiting for the user to tell when to go on sort dog cat * ...displays the lines of files dog and cat in sorted order * etc.! Many such UNIX utilities accept such INVOCATION ARGUMENTS, names of files to be processed in sequence; * And, many have as default that if NO such file names are given, they expect/accept keyboard input (standard input); cat more # OK, it'll complain that it can't accept input from the terminal! 8-) sort * People like to write UNIX-like utilities in Perl * (sometimes to port UNIX-like behavior to non-UNIX operating systems...! 8-) ) * SO --- how can you get behavior like that seen above in sort, cat, more? * the DIAMOND OPERATOR: <> * a "special kind of line-input operator" ("Learning Perl", p. 89) * instead of automatically getting the input from the keyboard --- it gets it "from the USER's choice of input" (LP, p. 89) * if user calls program with stuff on the command line? It'll try to grab from THOSE files; * (...unless one of those is a hyphen ( - ) --- that means standard input, too!) * if user calls with NO invocation arguments? Reads from the keyboard, as if had typed ; * so, while you CAN write: while (defined($line = <>)) { chomp($line); print "$line is what was input\n"; } * ...you can also write: while (<>) { chomp($_); print "$_ is what was input\n"; } ***** * small chomp detail.. ***** * by the way --- if chomp has NO argument --- it assumes it should chomp the default $_ ; * so, the above could also be written: while (<>) { chomp; print "$_ is what was input\n"; } * the difference is what happens when it runs! * above is in class5_03_diamond1 * try: class5_03_diamond1 class5_03_diamond1 class5_01_chomp1 class5_02_stdin1 class5_03_diamond1 class5_01_chomp1 - class5_02_stdin1 * NOTE: avoid using <> in more than one place within a program --- usually not correct... 8-) * NOTE #2: I didn't warn the user to type anything, did I? * that's because, in this kind of program, such prompts are awkward since user often users with invocation arguments instead of keyboard input; * yes, this DOES sometimes confuse novice users of UNIX utilities such as cat... 8-) #---------------------------------------------------------------------- @ARGV array * because, REALLY, that's what <> is using to grab the invocation arguments! * (and, yes, this, too, IS very C/C++-like... 8-) ) * @ARGV "...is a special array that is preset by the Perl interpreter to be a list of the invocation arguments" ("Learning Perl", p. 90) * ...and that's what <> uses. But a user can do so, too! * I like to write scripts that use invocation arguments if called with them, but write out prompts if NOT called with them; @ARGV makes that possible: # class5_04_ARGV1 # if no command-line arguments, ask user for desired input file, # set $ARGV[0] to that, so <> will read from it! if (@ARGV == 0) { print "enter name of file to be handled: "; $file = ; # a kluge! UNTIL we get to proper *file* input/output... $ARGV[0] = $file; } while (<>) { $line = $_; print "processing: $line"; # taking advantage of newline... } #------------------------------------------------------------------------ more about print * OK, we know that print just sends its arguments to standard output, no extra blanks, etc.; * (did we know? how about array interpolation? Ah, THAT's really because of DOUBLE-QUOTING the array, NOT because of print --- see? # class5_05_print1 print @ARGV, "\n"; print "@ARGV", "\n"; * (gotta run class5_05_print1 with command line arguments to see anything, of course... 8-) ) #------------------------------------------------------------------------- CLASSIC Perl confusion combined with the above (print with "@arr" vs. @arr) * imagine that you have an array of strings WITH newlines... @myLines * now imagine: print @myLines; print "@myLines"; * expect to see any difference? Let's see... # see class5_06_print2 * why that "shift"/indentation? * because, inside quotes, the array is INTERPOLATED to a string before it is printed --- string interpolation DOES intro a blank BETWEEN each pair of array elements, but NOT at beginning and end! (thus, each line AFTER first has an excess blank at beginning) * without quotes --- print just prints array contents, all smushed. But if newlines are there --- smushing not as obvious! 8-) #------------------------------------------------------------------- cute Perl-UNIX kinda-equivalencies... * a simple form of UNIX cat! print <>; * a simple form of UNIX sort! print sort <>; * ...these work because <> CAN return a list of lines in a list context; #------------------------------------------------------------------ being careful with print's optional parentheses * hey, we know about this already! (from first class session!) * "Learning Perl", p. 93: "another rule in Perl is that if the invocation of print *looks* like a function call, then it *is* a function call" print (2+4)*3; * thinks you asked it to print (2+4), then multiply print statement's return value by 3 and throw it away...! 8-) * you probably meant: print ((2+4)*3); * so, rule of thumb: ("Learning Perl", p. 94): "if print (or another function name) is followed by an open parenthesis, make sure that the corresponding close parenthesis comes after *all* of the arguments to that function." #------------------------------------------------------------------- printf * yes, comparable to C's printf! * printf "format string containing %format for each thing to print %format", $first_thing, $second_thing; printf "Hello, %s, your password expires in %d days\n", $user, $days_to_die; * %g --- pick "good" format for that as number...! * %d --- as a decimal integer, truncated if nec * %s --- the value as a string (no additional blanks before or after) * %6d --- ...right-justified in a field of size 6 * %10s --- a string right-justified in a field of size 10 * %-10s --- a string left-justified in a field of size 10 * %f --- a floating-point number * %12.3f --- a floating-point number in field of size 12, with three fractional places shown; INCLUDES decimal point!! * %.7f --- print to 7 fractional places, no additional blanks on either side * see pp. 94-96, "Learning Perl" * helpful tip: use string concatenation to "build" formatted array output; see "Learning Perl", p. 96 # end of 180class5_notes.txt