Perl Crash Course: Basic I/O

author: Valeria Paixão
revision: André Batosti
enhancement/translation: Vinny Alves

Note from UseStrict: Some of the examples in this tutorial were borrowed from Randall Schwartz’s Learning Perl. It’s a book that EVERY beginner Perl programmer should have. If you don’t have a hardcopy, please consider getting one. You can find it here: Learning Perl, 5th Edition

 

In this article, you will learn how to use basic I/O in Perl, learn about @ARGV, and become familiar with string formatting using printf.

STDIN

<STDIN> tells Perl to read from the standard input – usually the keyboard.

while (defined($_ = <STDIN>)) {
	print "I saw $_";  # echoes whatever is typed onto the screen. 
                                # Quit with ^D or ^Z (depending on your system)
}

foreach (<STDIN>) { 
        print "I saw $_"; # almost the same as above
} 

The difference between the while and foreach loops above is that while executes its statements at every hit of the return key, while foreach slurps into memory all the input until eof (^D on Unixes) and only then executes its instructions.

It is important to note this difference if you don’t want to crash your machine. If your input comes from a webserver with a 400MB log file, you’re better off processing each line individually than slurping it all into memory.


Diamond Operator

Another option to read data input is through the diamond operator (aka angle operator). It is handy to make Perl programs function like Unix commands such as cat, sed, awk, sort, grep, lpr, etc.

From the command line:
program_name.pl <file1> <file2> <someglob*>

In program_name.pl

while (<>)  { 	
	chomp; 
 	print "It was $_ that I saw!n"; 
} 

If you fail to give the program any parameters or pass it a dash (-), it will read from STDIN. The diamond operator will open each file and paste its contents into the special $_ variable. Just like any filehandle (more on filehandles here), you can slurp the input into an array in list context:

while ($line = <>)  { # populate $line instead of 	$_
	chomp($line); 
 	print "It was $line that I saw!n"; 
} 
# or 
@lines = <>;

for (@lines) {
     ... # do something with lines
}

If the diamond operator fails to open a passed file for reading, it will raise a warning and move on to the next file. It’s interesting to say that the diamond operator is quite intelligent: depending on how you call your script, it will not think that the parameters are files. For example:

cat some_file.txt | ./script.pl

The above example will work just as if you had sent it some_file.txt as a parameter.

@ARGV

@ARGV stores all the command line parameters passed to your script during run time. It is the array that the diamond operator looks at when doing its thing. You can manually manipulate it inside the script, as you would any other array, and the results will be as if you had passed your changes through the command line.


STDOUT

STDOUT is the default output channel for Perl’s print and printf functions.

print
print takes a list as parameters. The function returns 1 if successful and 0 otherwise. As we saw in our previous examples, the parentheses in the print function is not required. However, it may sometimes help you to get what you need.

Question1: what is the output for the snippet below?

       $result = print(2+3) * 4;
       print $result;

Check the bottom of this article for the answer.

If you want to print an array, as we saw in our Arrays and Lists post, you can get different results depending on which quotes (if any) you use.

print @colors;  # prints out 'redyellowblue'
print "@colors";  # prints out 'red yellow blue'
print '@colors';  # prints out '@colors' - no interpolation with single quotes, remember?

printf

printf allows you to have a better control of your output. It takes a format and the data to be formatted. Since printf is basically imported from C, and so many languages have adopted it, it accepts a wide range of popular patterns – even some deprecated ones:

%%	a percent sign
%c	a character with the given number
%s	a string
%d	a signed integer, in decimal
%u	an unsigned integer, in decimal
%o	an unsigned integer, in octal
%x	an unsigned integer, in hexadecimal
%e	a floating-point number, in scientific notation
%f	a floating-point number, in fixed decimal notation
%g	a floating-point number, in %e or %f notation

%X	like %x, but using upper-case letters
%E	like %e, but using an upper-case "E"
%G	like %g, but with an upper-case "E" (if applicable)
%b	an unsigned integer, in binary
%B	like %b, but using an upper-case "B" with the # flag
%p	a pointer (outputs the Perl value's address in hexadecimal)
%n	special: *stores* the number of characters output so far
        into the next variable in the parameter list

%i	a synonym for %d
%D	a synonym for %ld
%U	a synonym for %lu
%O	a synonym for %lo
%F	a synonym for %f

Each format can also take one or more of the following flags:

space	prefix positive number with a space
+	prefix positive number with a plus sign
-	left-justify within the field
0	use zeros, not spaces, to right-justify
#	ensure the leading "0" for any octal,
	prefix non-zero hexadecimal with "0x" or "0X",
	prefix non-zero binary with "0b" or "0B"

Some examples:

printf "%g %g %gn", 5/2, 51/17, 51 ** 17;	# 2.5 3 1.0683e+29
printf "in %d days!n", 17.85;				# in 17 days! 
printf "%10sn", "wilma";					# '     wilma' 
printf "%-15sn", "flintstone";				# 'flintstone     ' 
printf "%12fn", 6 * 7 + 2/3;					# '   42.666667'
printf "%12.3fn", 6 * 7 + 2/3;				# '      42.667'
printf "%12.0fn", 6 * 7 + 2/3;				#  '          43'
printf “Monthly interest: %.2f%%n", 5.25/12;	# Monthly interest: 

Answer to Question1: if you guessed 54, then congrats! The print(2+3) sends 5 to the screen and returns 1, which gets multiplied by 4 and assigned into $result. The following print $result sends 4 to the screen. Since there are no newlines anywhere in the data being printed, both digits get placed in the same line on the screen.

« Control Structures | TOC | Subroutines »

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.