printf is powerer to control the outputs, it's used with a format string, and a list of elements.
 
printf "Hello, $s; your password expires in %d days!\n", $user, $days_to_die;
printf "in %d days!\n", 17.85; # in 17 days!
 
Format string has some kind of 'conversion', each format string starts with '%' and ends with a character.
The number of elements and format strings must be the same, otherwise printf doesn't work.
 
%d gets integer number, like %d ... 17.85 is 17.
%s gets characters, -15 means align by left.
%f gets fload number.
 
printf "%6d\n",42;
printf "%2d\n",2e3+1.95;
printf "%15s\n","wilma";
printf "%-15s\n", "flintstone";
printf "%12f\n",6*7+2/3;
printf "%12.3f\n",6*7+2/3;
printf "%12.0f\n", 6*7+2/3;
 
$ ./printf.pl
Hello, Larry; your password expires in 5 days!
in 17 days!
    42
2001
          wilma
flintstone
   42.666667
      42.667
          43
 
If you want output a '%', use '%%', '\%' don't work.
printf "Monthly interest rate: %.2f%%\n", 5.25/12; # Monthly interest rate: 0.44%
 
Filehandle is the name of I/O connection in Perl program, is the bridge between perl and outside world.
It's name of connection, but not name of file.
 
Perl has six buildin filehandle: STDIN, STDOUT, STDERR, DATA, ARGV, ARGVOUT
STDIN=standard input
STDOUT=standard output
STDERR=standard error
 
If you need other filehandles, use operater 'open'.
open CONFIG, "dino"; # input from dino
open CONFIG, "<dino"; # input from dino
open BEDROCK, ">fred"; # output to fred, cover the original contents of fred
open LOG, ">>logile"; # append to fred
 
The upper-case are filehandles, the lower-case are filenames.
When opening a filehandle, the default action is get input from file, so the first two has same results.
We can use expressions with filenames.
 
my $selected_output="my_output";
open LOG, "> $selected_output"; # note the space after '>'
 
Use 'close' to close a filehandle.
close BEDROCK;
 
if(!open LOG, ">>logfile"){
 die "Cannot create logfile:$!";
 }
 
'die' will end program when 'open' fails, and tell you it cannot open logfile.
$! is the system error messages that shell throws out.
 
$ ./die_open.pl
Cannot create logfile:Permission denied at ./die_open.pl line 4.
 
If you don't want the program name, just put a "\n" at the end.
$ cat die_open.pl
#!/usr/bin/perl
if(!open LOG, ">>logfile"){
        die "Cannot create logfile:$!\n";
        }
  
$ ./die_open.pl
Cannot create logfile:Permission denied
 
After a filehandler opens, it can be used as STDIN to get input lines.
 
if(!open PASSWD, "/etc/passwd"){
 die "How did you get logged in?($!)";
 }
while(<PASSWD>){
 chomp;
 print "$_\n";
 }
 
$ ./die_open.pl
root:x:0:0:RHEL5:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
......

Exercises:

1. Write a program, print the reversed lines from input.

#!/usr/bin/perl

while(<>){
    push @lines,$_;
}

@lines=reverse @lines;
foreach(@lines){
    print $_;
}
###########################################

2. Write a program, user input lines of characters, then print the formatted lines that right align by 20 bits.

#!/usr/bin/perl

print "1234567890" x 7 . "\n";

while(<>){
    chomp;
    printf "%20s\n", $_;
}
###########################################

3. Modify the above program, let user input the align width.

#!/usr/bin/perl

chomp($width=<STDIN>);
print "1234567890" x $width . "\n";
while(<>){
    chomp;
    printf "%${width}s\n",$_;
}