C:\1980S\PERL.TXT
1987
Perl: The Glue Language Gets a Job
Early Perl joined text matching, associative arrays, and Unix process tools into a practical language for the work between larger programs.
Two programs agree to exchange data. One produces it in the format it likes. The other accepts it in the format it likes. A person now has a job.
Much useful computing happens in that uncelebrated gap. Files need filtering. Names need extracting. Repeated entries need counting. A report needs information gathered from several places, none of which was designed with the report in mind. The task may be too involved for one short command and too small to justify building a substantial application.
Larry Wall’s Perl addressed this kind of work with an unusually practical temperament. It brought facilities familiar from C, shell programming, sed, and awk into one language. The original manual described text extraction, reporting, and system management as central purposes. That is a sensible brief for software: there is a job waiting, and the job would prefer to be finished.1
The December release, before the web years
Perl’s maintained history records version 1.000 on December 18, 1987, followed by version 2.000 on June 5, 1988 and version 3.000 on October 18, 1989. All three sit inside this series’ decade.2
Wall was the language’s creator, and early distributions traveled through Unix networks and source newsgroups. Preserved distribution files include his original README and manual, allowing the early language to be examined rather than remembered from a later tutorial.3
The first Perl belongs to the Unix text-processing world. Its later importance in web programming is a different chapter. Perl 5’s object and module machinery, the CPAN ecosystem, and modern Unicode behavior shouldn’t be projected back into 1987. A young language can have a useful career before acquiring a much larger wardrobe.

Larry Wall in Houston, June 2007, photographed by Randal Schwartz. Later portrait, not a 1987 release photograph. Source; CC BY-SA 2.0. Existing crop and color correction retained; no additional alterations.
Text is a useful common denominator
Unix tools often work with streams of text. A command can write lines to its standard output; another can read those lines from standard input. Files preserve the same sort of material for later processing.
This arrangement is powerful because the connection is simple. The programs don’t have to share an elaborate object model or agree on one application’s internal file format. They do need agreement about the text’s structure, and that is where trouble likes to establish a residence.
For example, a field containing spaces can upset a script that treats every space as a separator. An added header line can become a fictitious data record. A number with a comma inserted for readability can defeat a program expecting only digits. “Plain text” doesn’t mean “no assumptions.”
Perl’s combination of regular expressions, string operations, arrays, and associative arrays made it possible to express those assumptions and the work that followed them in one program. Its early manual also documented pipes and command execution, keeping it close to the process environment in which the files were being produced.1
A report with only three lines of data
Consider this invented input:
cedar 12
cedar 5
elm 7
Each line gives a name and a nonnegative integer. We want a total for each name. The correct totals are cedar 17 and elm 7.
The following teaching program uses the older associative-array syntax documented in the Perl 1 manual:
while (<>) {
if (/^([a-z]+) +([0-9]+)\n?$/) {
$name = $1;
$amount = $2;
$totals{$name} += $amount;
}
else {
die "Malformed input line\n";
}
}
while (($name, $total) = each(totals)) {
print "$name: $total\n";
}
This is an explanatory program, not a recovered script by Wall. The original each(totals) notation also reminds us that early Perl isn’t exactly the language installed on a modern machine. A current version uses each(%totals) for that operation.
The <> input operator reads from the filenames provided on the command line, or from standard input when no filenames are supplied. In the while condition, each input line becomes the current default string, $_. The pattern match then uses that string without requiring it to be named again.4
The pattern begins with ^, anchoring it at the start. ([a-z]+) accepts one or more lower-case letters and captures them. One or more spaces follow. ([0-9]+) captures one or more digits. The optional newline accommodates the line ending, and $ marks the end condition. The two parenthesized captures become $1 and $2.
That intentionally narrow grammar excludes names with spaces, negative numbers, decimals, and stray trailing comments. Rejecting them is appropriate for this tiny input contract. A real report must define the contract it actually needs; merely making the pattern more permissive is not automatically an improvement.
The table hidden behind the braces
$totals{$name} names one value in an associative array, a collection indexed by keys rather than only by consecutive numeric positions. Modern Perl usually calls this collection a hash. If the name is cedar, the program selects cedar’s running total.
The first cedar line contributes 12. The second contributes 5 to the same entry, producing 17. The elm line selects a different entry and contributes 7. Early Perl initialized values in ways that made this accumulation convenient: a previously unset numeric value could start from zero.5
The algorithm needn’t know all the names in advance. It discovers keys while reading the input. Nor must it store every line. After processing a line, it can keep only the updated total for that name.
For an input with a million lines but only a hundred distinct names, the accumulated table can remain much smaller than the original text. The precise memory overhead depends on the implementation, but the distinction between storing every record and storing one result per group is fundamental.
Original explanatory illustration, 2026. Invented data. Totals may emerge in either order from associative-array iteration; alphabetical ordering is a separate display step.
each walks through the entries and returns a key and a value. The original manual expressly warns that the order appears arbitrary. The arithmetic result is defined; the displayed order isn’t. If the report needs alphabetic order, sorting is a separate operation. Early Perl’s manual shows cooperation with the Unix sort command rather than assuming every modern built-in was already present.6
This is a useful distinction in any data-processing tool. A correct aggregate can still produce unstable presentation order. Someone comparing two reports may otherwise spend an afternoon investigating a change that consists entirely of rows moving about.
Regular expressions are a language inside the language
A regular expression describes a pattern in text. It can answer whether the pattern exists, identify matching parts, and guide a substitution. The benefit is that a recurring structure can be stated compactly without writing a character-by-character scanner for every task.
In the example, the whole line is validated before its parts become data. A looser search for a number somewhere in the line could accidentally accept an unrelated entry. Patterns are executable assumptions, and assumptions deserve to be visible.
They also have limits. A pattern suitable for a simple report doesn’t automatically understand quoted fields, nested syntax, or arbitrary document structure. Some problems need a parser with a proper grammar. Others need a few well chosen string operations. Regex punctuation is not a measure of seriousness.
The implementation changed during the decade. Wall’s historical summary notes that Perl 2 introduced Henry Spencer’s regular expression package, and Perl 3 added the ability to handle embedded null bytes in binary data. Those are substantial version boundaries. The first release shouldn’t inherit the later engine or binary-data capability.2
Convenience needs discipline
Perl’s defaults save repetition. The current line can be implicit; strings can be interpreted numerically when the operation requires it; a little program can perform work without a large block of declarations. For the short extraction job, this lowers the distance between describing the task and running it.
But an implicit value is still a value the reader must track. If several operations use or change the current default string, a compact script can become difficult to follow. Naming intermediate values, as the example does with $name and $amount, makes the flow easier to inspect even when the language could omit them.
The early manual also supplied report formats, making formatted textual output a built-in concern. That detail helps explain Perl’s original name in the manual, Practical Extraction and Report Language. Reports were part of the intended work, not an incidental afterthought.7
I like the pragmatism of this design, with one qualification: saving keystrokes is useful when it preserves the next reader’s understanding. The next reader may be the same author six months later, operating without the original enthusiasm.
The work between systems deserves a language
The example’s processing logic was checked with a modern Perl after adapting the old each notation. It produced the expected totals and rejected a malformed line. That establishes the teaching example’s logic; it doesn’t claim execution under an untouched December 1987 interpreter.
What matters historically is the combination available to early users. They could read files, recognize text, accumulate information by key, produce reports, and coordinate other Unix tools within one practical language.
Perl gave the small integration job room to grow beyond a brittle command line without immediately demanding the ceremony of a much larger implementation. That kind of work rarely appears in a product demonstration. It often determines whether the rest of the system is useful on Monday morning.
Footnotes
-
Larry Wall, Perl 1 manual, preserved in Perl 1 reconstruction repository, opening description and process operations. Repository modernization is distinguished from original runtime behavior. ↩ ↩2
-
Perl maintainers,
perlhist, release records and Larry Wall’s version summary. ↩ ↩2 -
Larry Wall, original Perl Kit README, with source-posting provenance preserved by the reconstruction project. These files are not used as first-release date evidence. ↩
-
Perl 1 manual, input operators and loop syntax. ↩
-
Same manual, “Data Types and Objects” and initialization behavior. ↩
-
Same manual,
each,keys, andcloseexamples involving pipes tosort. ↩ -
Same manual, report-format declarations and
write. ↩