Home / Alt manpages / perlintro(1)

  • perlintro(1)
  • User command
  • linux

Start Writing Small, Safer Perl Programs with perlintro

You will finish with a small Perl script that reads text, counts matching lines and prints a result. Along the way you will use the safety checks, variables, loops, file input and regular expressions introduced by the installed perlintro(1) guide. Allow about fifteen minutes. You need a shell, a text editor and the perl-doc package if you want to read the guide locally.

The examples here describe Perl v5.38.2, the version installed on this machine. Perl has a large history and several ways to express the same task, so treat this as a reliable starting path rather than a complete language reference.

1. Check the interpreter and read the guide

Start with read-only checks. They do not need elevated privileges and make it clear which Perl installation will run your script:

$ command -v perl
/usr/bin/perl
$ perl -v
This is perl 5, version 38, subversion 2 (v5.38.2)
$ perldoc -l perlintro
/usr/share/perl/5.38/pod/perlintro.pod

If perldoc cannot find the document, install the distribution's documentation package through your normal package manager. Do not use sudo merely to run Perl or to read its documentation. Package installation changes system state and may require an administrator, but it is not needed for the script below if perl already runs.

Checkpoint: confirm that perl -v reports the interpreter you intend to use. A script can work with one Perl installation and fail with another if their modules or feature versions differ.

2. Create a script with the safety net enabled

Create line-count.pl in a working directory. The first line lets the shell find Perl through env; the next two declarations catch common mistakes. strict can stop compilation when it sees unsafe variable use. warnings reports suspicious behaviour while allowing execution to continue where possible.

#!/usr/bin/env perl
use strict;
use warnings;

my $needle = shift @ARGV // 'error';
my $matches = 0;

while (<>) {
    if (/$needle/) {
        $matches++;
    }
}

print "matches: $matches\n";

Make it executable, then run Perl explicitly for the first test. This avoids mixing file permissions with language errors:

$ chmod 755 line-count.pl
$ printf 'ok\nerror: disk full\nok\n' | perl line-count.pl
matches: 1

The <> operator reads from files named on the command line, or from standard input when the shell pipe supplies it. Each iteration places one line in Perl's default variable, $_. The regular expression between slashes tests that line. The expression is intentionally small, but it is not a literal-string search: characters in $needle are interpreted as regular-expression syntax.

3. Understand the values before adding features

Perl's three main variable types are scalars, arrays and hashes. A scalar holds one value, an array holds an ordered list and a hash holds key/value pairs. Their sigils are $, @ and %. Use my for variables local to the current scope. This keeps a typo from silently creating a package-wide variable when strict is enabled.

my $animal = 'camel';
my @animals = ('camel', 'llama', 'owl');
my %colour = (
    apple  => 'red',
    banana => 'yellow',
);

print "$animal\n";
print $animals[1], "\n";
print $colour{'apple'}, "\n";

Double-quoted strings interpolate variables and escapes such as \n. Single-quoted strings normally keep those characters literal. Arrays start at index zero. A hash has no guaranteed internal order, so sort its keys when stable output matters:

for my $fruit (sort keys %colour) {
    print "$fruit: $colour{$fruit}\n";
}

Checkpoint: if a short example fails, run perl line-count.pl again and read the first warning or error. Fix that first report before adding another feature. A long stream of warnings is a distraction, not useful progress.

4. Make file handling explicit

For a reusable program, open a named file rather than relying only on standard input. The three-argument form of open keeps the mode separate from the path. The or die branch turns a missing or unreadable file into a useful failure instead of silently continuing.

my $path = shift @ARGV // 'input.txt';
open(my $input, '<', $path) or die "Cannot open $path: $!\n";

while (my $line = <$input>) {
    print $line if $line =~ /error/i;
}

close $input or die "Cannot close $path: $!\n";

The < mode is for input. The manual also documents > for output, which truncates an existing file, and >> for appending. Treat those as state-changing operations: check the destination before running them and do not use them against an important file until you have a tested replacement plan. If you accidentally create an unwanted output file, remove only that known file after checking its path; there is no general undo for a truncating open.

Run the read-only version against a deliberate fixture:

$ printf 'ok\nERROR: retry\n' > /tmp/perl-input.txt
$ perl line-count.pl /tmp/perl-input.txt
matches: 0

That result is expected because the first script's default pattern is the word error only when it is supplied. The file-reading example uses /error/i, which ignores case. Keep the distinction visible when debugging: a pattern, its flags and the input all affect the result.

5. Use regexes without surprising the shell

A simple match uses /pattern/ against $_, or $value =~ /pattern/ against a named scalar. Common pieces include \d for a digit, \s for whitespace, brackets for a character set, + for one or more repetitions and ^ and $ for the start and end of a string.

while (<>) {
    if (/^ERROR:\s+/) {
        print "found: $_";
    }
}

When the pattern comes from a user or a file, validate what you intend to accept. A value such as . does not mean a literal full stop in a regular expression. If you need literal matching for an arbitrary string, use the documented quoting tools rather than assuming the input is harmless. Keep shell quoting separate from Perl quoting: single quotes around a shell argument stop the shell expanding characters before Perl receives them.

6. Inspect errors and keep the next step small

Run a syntax check without executing the script:

$ perl -c line-count.pl
line-count.pl syntax OK

If you see a compile-time error, check semicolons, braces, variable declarations and spelling. If the script compiles but produces the wrong count, print a carefully chosen value or test with a three-line fixture. The manual points to perlsyn, perldata, perlfunc and perlretut when the brief overview stops being enough. Use perldoc -f print to inspect one built-in function and perldoc perlretut for the regular-expression tutorial.

Keep the original input while testing. The examples read files and write only to standard output, apart from the explicitly created temporary fixture. No service restart or root access is involved.

Done means

  • perl -v identified the interpreter you meant to use.
  • The script starts with use strict; and use warnings;.
  • perl -c line-count.pl reports syntax OK.
  • A known three-line input produced the expected match count.
  • File modes were chosen deliberately, and no important file was opened with truncating >.
  • You know to consult the focused Perl manual page when the brief introduction is no longer sufficient.