Skip to content

Perl Formats

Important Note: Perl’s format and write features for report generation are largely considered legacy. While they are part of Perl’s core, modern Perl development overwhelmingly favors templating engines (e.g., Template Toolkit, Text::Template, Mojo::Template) for generating text reports, HTML, or other structured text outputs. These engines offer more flexibility, power, and maintainability. This section describes Perl formats for completeness, but their use in new projects is generally discouraged.

Perl’s format feature allows you to define templates for generating simple, fixed-column reports. You define a format and then use the write keyword to output data according to that template.

A format is declared using the format keyword, followed by a name (which is often tied to a filehandle name), an equals sign, and then lines defining the layout, ending with a single period (.) on a line by itself.

Syntax:

format FormatName =
field_line_1
value_line_1_var1, value_line_1_var2, ...
field_line_2
value_line_2_var1, value_line_2_var2, ...
.
  • FormatName: The name of the format. By default, Perl looks for a format named after the current output filehandle (e.g., STDOUT if printing to standard output).
  • field_line: Contains literal text and picture fields (fieldholders) that define how values should be formatted.
  • value_line: A list of variables or expressions whose values will be inserted into the fieldholders in the preceding field_line.

Fieldholders specify how data is placed and formatted within the field_line.

  • @<<<< : Left-justified text field. The number of < plus the @ determines the field width.
  • @>>>> : Right-justified text field.
  • @|||| : Centered text field.
  • @###.## : Numeric field. # represents a digit position. The . is the decimal point. Output is right-justified.
  • @* : Multiline text field. Used for values that might contain newlines. The value is printed, and if it doesn’t fill the current line, format processing continues on the next line with the rest of the value.

Example of a format definition:

#!/usr/bin/env perl
use strict;
use warnings;
# Variables that will be used by the format
our ($name, $age, $salary);
format EMPLOYEE_RECORD =
=====================================
Name: @<<<<<<<<<<<<<<<<<<<<< Age: @<<
$name, $age
Salary: @#####.##
$salary
-------------------------------------
.

In this example, $name will be left-justified in a 25-character wide field (including the @), $age in a 2-character field, and $salary formatted as a number with up to 5 digits before the decimal and 2 after.

The write keyword outputs data using a defined format. write sends its output to the currently selected filehandle (see select()). To use a specific format, you associate it with a filehandle using the special variable $~ (or $FORMAT_NAME if use English; is active).

#!/usr/bin/env perl
use strict;
use warnings;
# Declare package variables that format will use
our ($name, $age, $salary);
# Define the format (as above)
format EMPLOYEE_RECORD =
=====================================
Name: @<<<<<<<<<<<<<<<<<<<<< Age: @<<
$name, $age
Salary: @#####.##
$salary
-------------------------------------
.
# Select STDOUT as the output filehandle for write
select(STDOUT);
# Associate the EMPLOYEE_RECORD format with STDOUT
$~ = "EMPLOYEE_RECORD";
# Data for the report
my @employees = (
{ name => "Alice Wonderland", age => 30, salary => 55000.75 },
{ name => "Bob The Builder", age => 42, salary => 62000.50 },
{ name => "Charlie Brown", age => 8, salary => 10.00 },
);
foreach my $emp_data (@employees) {
# Assign values to the package variables used by the format
$name = $emp_data->{name};
$age = $emp_data->{age};
$salary = $emp_data->{salary};
write; # Output one record using the EMPLOYEE_RECORD format to STDOUT
}

When executed, this produces:

=====================================
Name: Alice Wonderland Age: 30
Salary: 55000.75
-------------------------------------
=====================================
Name: Bob The Builder Age: 42
Salary: 62000.50
-------------------------------------
=====================================
Name: Charlie Brown Age: 8
Salary: 10.00
-------------------------------------

You can define a header format that will be printed at the top of each page. The name of this header format is typically FILEHANDLE_TOP (e.g., STDOUT_TOP). You assign the name of your header format to the special variable $^ (or $FORMAT_TOP_NAME).

#!/usr/bin/env perl
use strict;
use warnings;
our ($name, $age, $salary); # For EMPLOYEE_RECORD
our ($page_num); # For STDOUT_TOP
format STDOUT_TOP =
Employee Report Page: @<
$page_num
----------------------------------------------------------
Name Age Salary
----------------------------------------------------------
.
format EMPLOYEE_RECORD =
@<<<<<<<<<<<<<<<<<<<<<<< @<< @##########.##
$name, $age, $salary
.
select(STDOUT);
$~ = "EMPLOYEE_RECORD";
$^ = "STDOUT_TOP"; # Set the top-of-page format
# Simulate multiple employees to potentially span pages (if page length was set smaller)
my @employees_data = (
{ name => "Alice", age => 30, salary => 55000 },
{ name => "Bob", age => 42, salary => 62000 },
# ... add more employees to see pagination if $= is small
);
$page_num = 0; # Initialize page number, will be updated by $% or manually
foreach my $emp_data (@employees_data) {
# Before each write, Perl checks if a new page is needed.
# If so, it increments $FORMAT_PAGE_NUMBER ($%) and prints the _TOP format.
# We need to ensure our $page_num reflects this for the header.
$page_num = $%; # $FORMAT_PAGE_NUMBER
if ($FORMAT_LINES_LEFT <= 3) { # Check if close to bottom, heuristic for page break
$page_num++; # Manually anticipate if needed, or rely on $% before write
}
$name = $emp_data->{name};
$age = $emp_data->{age};
$salary = $emp_data->{salary};
write;
}

Pagination: Page Numbers and Lines Per Page

Section titled “Pagination: Page Numbers and Lines Per Page”

Perl automatically handles pagination to some extent when using formats.

  • $% (or $FORMAT_PAGE_NUMBER): Contains the current page number. It’s incremented automatically when a page break occurs.
  • $= (or $FORMAT_LINES_PER_PAGE): Specifies the number of printable lines per page. Default is 60. You can set this to control page length.
  • $- (or $FORMAT_LINES_LEFT): Contains the number of lines remaining on the current page. When this reaches 0 (or less, due to multi-line fields), a new page is started, the _TOP format is printed, and $- is reset to $=.

To include the page number in your header (like in STDOUT_TOP example above), use $% in the value line of the header format.

format STDOUT_TOP =
Employee Report Page @<<<
$%
------------------------------------
Name Age Salary
------------------------------------
.

Perl does not have an automatic mechanism for footers equivalent to $^ for headers. If you need a footer, you must implement it manually. This usually involves checking $- (lines left) before each write. If $- is low enough that the next record (plus the footer) won’t fit, you print the footer using a separate format definition, then manually trigger a page break (e.g., by printing newlines until $- is 0 or by writing a special blank record that fills the page), or print the footer and then the header for the new page.

format EMPLOYEE_FOOTER =
End of Page @<.
$%
====================================
.

You would then call write EMPLOYEE_FOOTER; conditionally.

As reiterated, for any new development requiring report generation or text templating, consider modern CPAN modules like Template Toolkit, Text::Template, or others that offer far more capabilities and are easier to maintain than Perl’s built-in format system.