Contents


9. Loops and I/O

Example: Command Line Values and Iterative Loops

 print "$#ARGV is the subscript of the ",
 "last command argument.\n";
 # Iterate on numeric subscript 0 to $#ARGV:
 for ($i=0; $i <= $#ARGV; $i++) {
 print "Argument $i is $ARGV[$i].\n";
 }
 # A variation on the preceding loop:
 foreach $item (@ARGV) {
 print "The word is: $item.\n";
 }
 # A similar variation, using the
 # "Default Scalar Variable" $_ :
 foreach (@ARGV) {
 print "Say: $_.\n";
 }
Demonstration:
 > perl example5.pl Gooood morning, Columbia!
 2 is the subscript of the last command argument.
 Argument 0 is Gooood.
 Argument 1 is morning,.
 Argument 2 is Columbia!.
 The word is: Gooood.
 The word is: morning,.
 The word is: Columbia!.
 Say: Gooood.
 Say: morning,.
 Say: Columbia!.

Example: Standard I/O

 print STDOUT "Tell me something: ";
 while ($input = <STDIN>) {
 print STDOUT "You said, quote: $input endquote\n";
 chop $input;
 print STDOUT "Without the newline: $input endquote\n";
 if ($input eq '') { print STDERR "Null input!\n"; }
 print STDOUT "Tell me more, or ^D to end:\n";
 }
 print STDOUT "That's all!\n";
Note 1: The while statement's condition is an assignment statement: assign the next record from standard input to the variable $input. On end of file, this will assign not a null value but an "undefined" value. An undefined value in the context of a condition evaluates to "false". So the "while ($input = <STDIN>)" does three things: gets a record, assigns it to $input, and tests whether $input is undefined. In other contexts, Perl treats an undefined variable as null or zero. Thus, if $i is not initialized, $i++ sets $i to 1. Perl Paradox Number Three: Side effects can yield an elegant face or a pain in the rear.

Note 2: Data records are by default terminated by a newline character "\n" which in the above example is included as the last character of variable $input. The "chop" function removes the last character of its argument. Perl 5 introduces a "chomp" function that removes the last characters of a variable only if they are the currently defined end-of-record sequence, which is defined in the special variable $/.

Demonstration:

 > perl example6.pl
 Tell me something: I'm warm.
 You said, quote: I'm warm.
 endquote
 Without the newline: I'm warm. endquote
 Tell me more, or ^D to end:
 Can I have some water?
 You said, quote: Can I have some water?
 endquote
 Without the newline: Can I have some water? endquote
 Tell me more, or ^D to end:
 You said, quote:
 endquote
 Without the newline: endquote
 Null input!
 Tell me more, or ^D to end:
 ^D
 That's all!

Example: Perls, A Perl Shell, Calculator, & Learning Tool

 #!/usr/local/bin/perl
 for (;;) {
	print '(',join(', ',@ReSuLt),') ?';
	last unless $InPuT = <STDIN>;
	$? = ''; $@ = ''; $! = ''; 
	@ReSuLt = eval $InPuT;
	if ($?) { print 'status=',$?,' ' }
	if ($@) { print 'errmsg=',$@,' ' }
	if ($!) { print 'errno=',$!+0,': ',$!,' ' }
 }
This reads a line from the terminal and executes it as a Perl program. The "for (;;) {...}" makes an endless loop. The "last unless" line might be equivalently specified:
 $InPuT = <STDIN>; # Get line from standard input.
 if (! defined($InPuT)) {last;} # If no line, leave the loop.
The "eval" function in Perl evaluates a string as a Perl program. "$@" is the Perl error message from the last "eval" or "do".

Demonstration:

 perls
 () ?Howdy
 (Howdy) ?2+5
 (7) ?sqrt(2)
 (1.4142135623730951) ?$x
 () ?$x = sqrt(2)
 (1.4142135623730951) ?$x + 5
 (6.4142135623730949) ?1/0
 errmsg=Illegal division by constant zero in file (eval) at line 2, next 2 tokens "0;"
 () ?system 'date'
 Fri Sep 27 10:02:43 CDT 1996
 (0) ?$x = `date`
 (Fri Sep 27 10:02:52 CDT 1996
 ) ?chop $x
 (
 ) ?$x
 (Fri Sep 27 10:02:52 CDT 1996) ?@y = split(/ /,$x)
 (Fri, Sep, 27, 10:02:52, CDT, 1996) ?@y[1,2,5]
 (Sep, 27, 1996) ?localtime()
 (37, 4, 10, 27, 8, 96, 5, 270, 1) ?
 () ?foreach (1..10) {print sqrt(),' '}
 1 1.4142135623730951 1.7320508075688772 2 2.2360679774997898 
 2.4494897427831779 2.6457513110645907 2.8284271247461903 3 3.1622776601683795 
 () ?exit

Example: File I/O

 #!/usr/local/bin/perl
 # Function: Reverse each line of a file
 # 1: Get command line values:
 if ($#ARGV !=1) {
 die "Usage: 0ドル inputfile outputfile\n";
 }
 ($infile,$outfile) = @ARGV;
 if (! -r $infile) {
 die "Can't read input $infile\n";
 }
 if (! -f $infile) {
 die "Input $infile is not a plain file\n";
 }
 # 2: Validate files
 # Or statements "||" short-circuit, so that if an early part
 # evaluates as true, Perl doesn't bother to evaluate the rest.
 # Here, if the file opens successfully, we don't abort:
 open(INPUT,"<$infile") ||
 die "Can't input $infile $!";
 if ( -e $outfile) {
 print STDERR "Output file $outfile exists!\n";
 until ($ans eq 'r' || $ans eq 'a' || $ans eq 'e' ) {
 print STDERR "replace, append, or exit? ";
 $ans = getc(STDIN);
 }
 if ($ans eq 'e') {exit}
 }
 if ($ans eq 'a') {$mode='>>'}
 else {$mode='>'}
 open(OUTPUT,"$mode$outfile") ||
 die "Can't output $outfile $!";
 # 3: Read input, reverse each line, output it.
 while (<INPUT>) {
 chop $_;
 $_ = reverse $_;
 print OUTPUT $_,"\n";
 }
 # 4: Done!
 close INPUT,OUTPUT;
 exit;


[an error occurred while processing this directive]

AltStyle によって変換されたページ (->オリジナル) /