Perl · Course navigation

Perl file handles on strings and formatted output

Read lines from a string as if from a file, validate each line, and write formatted output to a string.

On this page
Before you start

Perl scalars, loops, and regular expressions.

  • Read lines from a string as if from a file, validate each line, and write formatted output to a string.
  • Predict the sample output and explain the state changes.
  • Complete the practice task and check the boundary cases.

The concept

Perl reads and writes files through file handles. open(my $in, '<', $path) opens a file for reading, and the diamond operator <$in> reads one line at a time. If the file name is replaced by a reference to a string, \$data, the same code reads from or writes to that string in memory. That is handy for testing code that normally uses files, and it works the same way everywhere.

chomp removes the trailing newline from a line, and split ' ' splits on any white space. Checking the pieces with a regular expression protects the program against bad input. printf writes formatted text, and print {$fh} sends output to a particular handle. Always check the result of open and close the handle when finished.

Code example

Perl
use strict;
use warnings;

my $data = "alpha 3\nbeta 5\ngamma x\n";
open(my $in, '<', \$data) or die "cannot open: $!";
my $total = 0;
while (my $line = <$in>) {
    chomp $line;
    my ($name, $value) = split ' ', $line;
    if ($value =~ /^\d+$/) {
        print "$name=$value\n";
        $total += $value;
    } else {
        print "bad line: $line\n";
    }
}
close $in;
print "total $total\n";

my $report = '';
open(my $out, '>', \$report) or die "cannot open: $!";
printf $out "%-6s|%3d\n", "ab", 7;
print {$out} "done\n";
close $out;
print $report;
Output
alpha=3
beta=5
bad line: gamma x
total 8
ab    |  7
done

Follow the code

Open the walkthrough to inspect the example one step at a time.

Show guided walkthrough
Guided walkthroughReady
1use strict;
2use warnings;
3
4my $data = "alpha 3\nbeta 5\ngamma x\n";
5open(my $in, '<', \$data) or die "cannot open: $!";
6my $total = 0;
7while (my $line = <$in>) {
8 chomp $line;
9 my ($name, $value) = split ' ', $line;
10 if ($value =~ /^\d+$/) {
11 print "$name=$value\n";
12 $total += $value;
13 } else {
14 print "bad line: $line\n";
15 }
16}
17close $in;
18print "total $total\n";
19
20my $report = '';
21open(my $out, '>', \$report) or die "cannot open: $!";
22printf $out "%-6s|%3d\n", "ab", 7;
23print {$out} "done\n";
24close $out;
25print $report;

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
Opening a reference to a string gives a file handle that reads from the string.—
—
Read one line per pass until the end of the data.—
—
Split on white space into a name and a value.—
—
Only digits are accepted as a number.—
—
Valid lines are printed and added up.—
alpha=3
beta=5
The third line has x instead of a number.—
alpha=3
beta=5
bad line: gamma x
3 + 5.—
alpha=3
beta=5
bad line: gamma x
total 8
Formatted output goes to the string handle: left-aligned text and a right-aligned number.—
alpha=3
beta=5
bad line: gamma x
total 8
The collected output is printed at the end.—
alpha=3
beta=5
bad line: gamma x
total 8
ab    |  7
done

Behind the scenes

How Perl processes this code

Perl compiles the script internally before executing it. strict and warnings help identify mistakes.

Cost and common mistakes

Reading is O(n) for n characters.

  • A line read with <$in> still ends with a newline. Forgetting chomp makes comparisons and numeric checks fail.
  • split ' ' with a single space is special: it splits on runs of white space and ignores leading white space, unlike split / /.
  • Always check open. In real programs the file may be missing or unreadable, and $! tells why.

Try it yourself

How do you read from a real file instead?

Reveal answer and reasoning

Replace \$data with the file name: open(my $in, '<', 'data.txt') or die ...

Further reading