Here's one way to do it:
print "What column width would you like? ";
chomp(my $width = <STDIN>);
print "Enter some lines, then press Ctrl-D:\n"; # or Ctrl-Z
chomp(my @lines = <STDIN>);
print "1234567890" x (($width+9)/10), "\n"; # ruler line as needed
foreach (@lines) {
printf "%${width}s\n", $_;
}
This is much like the previous one, but we ask for a column width
first. We ask for that first because we can't ask for more
input after the end-of-file indicator, at least
on some systems. Of course, in the real world, you'll generally
have a better end-of-input indicator when getting input from the
user, as we'll see in later chapters.
Another change from the previous exercise's answer is the ruler
line. We used some math to cook up a ruler line that's at least
as long as we need, as suggested as an "extra credit"
part of the exercise. Proving that our math is correct is an
additional challenge. (Hint: Consider possible widths of
50 and 51, and remember that
the right side operand to x is truncated, not
rounded.)
To generate the format this time, we used the expression
"%${width}s\n", which interpolates
$width. The curly braces are required to
"insulate" the name from the following
s; without the curly braces, we'd be
interpolating $widths, the wrong variable. If you
forgot how to use curly braces to do this, though, you could have
written an expression like '%' . $width . "s\n" to
get the same format string.
The value of $width brings up another case where
chomp is vital. If the width isn't
chomped, the resulting format string would resemble
"%30\ns\n". That's not useful.
People who have seen printf before may have
thought of another solution. Because printf
comes to us from C, which doesn't have string interpolation, we
can use the same trick that C programmers use. If an asterisk
("*") appears in place of a numeric
field width in a conversion, a value from the list of parameters will
be used:
printf "%*s\n", $width, $_;