table-written Tables with groff tbl

Using the tbl pre-processor with groff, you can create sophisticated tables with a variety of styles.

In Unix history, the troff program first appeared in Unix 4th Edition, in November 1973. This was an update to the nroff document processing system, now supporting the Unix team's new C/A/T phototypesetter. A typesetter is similar to a modern laser printer, although it uses a different method to put ink onto paper. Where nroff was short for "new roff," the name troff stood for "typesetter roff."

Using a typesetter meant the Unix team could produce professional looking documents, including fonts, formatting, and line-drawing. To add tables to printed documents, the Unix team created the tbl pre-processor program, included in Unix 6th Edition. This program interprets a troff document, specifically any instructions between the .TS and .TE requests, and generates formatting instructions that troff can use to draw a table.

Creating tables

Most modern Unix and Linux systems have replaced troff with GNU groff, which also provides a tbl pre-processor that operates in the same way. The top of a table definition indicates how to display the table data. You can align columns to the left, right, center, or by the decimal point. For example, this block creates a single table with three columns, where the first column is left aligned, the middle column is centered, and the third column is right aligned:

l c r.

The first line provides the column specifications: l c r. means the table has three columns that are left, center, and right aligned. The period indicates the end of the column specifiers.

The rest of the data indicates the table data. Each column in the table data must be separated by a tab, which I've represented with .

Historically, you'd process a troff file that includes tables by running the tbl pre-processor separately, then sending the result to the troff program. However, GNU groff accepts the -t option to run the tbl pre-processor for you. These two commands are the same:

$ tbl simple | groff -me -Tps >
$ groff -t -me -Tps simple >

I've processed this document using the -me macros, although the tbl pre-processor doesn't care what macro package you use for the rest of your document. You should be able to use tables with any macro set. For example, my simple document only generates a table, and doesn't use the -me macros at all; I'm using -me only to set the page margins correctly.

A simple table in groff tbl

A simple table in groff tbl

Adding an outline

To add other specifications to the table, you can add keywords before the column specifiers.  For example, box will outline the generated table in a single box, and allbox will put every cell in a box of its own. I also like to replace the tab delimiter with another character, so I can see it more easily in my document. To replace the tab with the @ character, use tab(@). End the list of keywords with a semicolon.

This table sample lists several common options you can use on tables:

center allbox tab(@);
c l.
box@Surround the table in a box
doublebox@Surround the table in a double-lined box
allbox@Put each cell in a box
center@Center the table horizontally
expand@Make the table as wide as possible
tab(c)@Change the column delimiter from tab to c

Processing this document with tbl and groff generates a handy reference about how to use table options:

$ tbl options | groff -me -Tps >

Common options in tbl

Common options in tbl

Changing the columns

In the above examples, we've used a single line to specify the alignments for each column, and every row in the table uses the same alignments. You can add other lines to indicate specific column alignments for different rows.

For example, we might center the first row to create a header row, and left align the other rows. Each line of column specifiers will be matched with a separate row in the tables; four tables rows that use different column alignments require four lines of column specifiers:

center allbox tab(@);
c c c
l c r
c r l
r l c.
column A@column B@column C

This generates a four-row table where each cell in the first row is centered, and every row afterwards uses a different order of column alignments.

Column options in tbl

Column options in tbl

Advanced formatting

Tables can include more sophisticated than just boxed cells with values. You can generate almost any combination of formatting using tbl. Let's say you wanted to generate a table with custom formatting: a header row with centered bold text, a double line under that, and data rows separated with a single vertical line. To make a list of numbers and their associated name, we also might need to align the values by the decimal point.

This advanced formatting requires a few extra specifiers. To make text bold, append b to the column specifier. To format in italics, append i instead. You can use other special suffixes to apply other formatting, such as changing the font or the size. The "Column specifiers" section in the tbl(1) manual page provides a full list of options.

A vertical bar (|) for a column specifier turns that column into a vertical line. Insert a horizontal line to the table using a hyphen (-) for the specifier. Use an equals sign (=) to make a double line instead. The "Table format specification" section in the tbl(1) manual page lists other ways to format a table, including spanning rows and columns.

With this understanding, we can create a table of numerical values and their associated name. Note that the numbers are aligned to the decimal point using the n specifier.

center tab(@);
cb |  cb
=  =  =
n  |  li.

I've added extra spacing in the column specifiers so you can more easily see how things line up.

Plain formatting in tbl

Plain formatting in tbl

Sometimes, technical information can best be represented by a table rather than in words. Tables can show relationships between information, list data or observations from experiments, or order information by category. If you need to include a table in your next groff document, use tbl to make it look great.