Skip to content
VLSI Mentor

Perl Part I · Module 15 · Command-Line Perl and Script Execution

One-Liners: perl -e

Not every job deserves a file. Counting how many lines of a report mention a particular pin, converting a column of picoseconds to nanoseconds, checking whether two netlists have the same set of names — these take one line, you will do them once, and creating a script for them is slower than doing them. perl -e takes the whole program as a command-line argument and runs it immediately. The flags that go with it turn a cramped expression into something readable, and the one thing that genuinely catches people out is not Perl at all: it is the shell, which reads your program text before Perl does and will quietly rewrite parts of it unless you quote it correctly.

Intermediate13 min readPerlPart ICommand Line

Part I · Module 15 · Chapter 15.6 · One-Liners: perl -e

1. The Whole Idea

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
perl -e 'print "hello\n"'

-e says "the next argument is the program". There is no file, nothing is saved, and Perl exits when it finishes. Everything the language can do is available — this is not a cut-down mode.

Azvya Education Pvt. Ltd.VLSI Mentor
e-basics.pl
use strict;
use warnings;

# each row runs a real one-liner and shows what came back
my @demo = (
    [ q{perl -e 'print "hello\n"'},             "the simplest form" ],
    [ q{perl -e 'my $x = 6;' -e 'print $x*7, "\n"'}, "two -e options, one program" ],
    [ q{perl -E 'say "say needs -E"'},          "-E switches on modern features" ],
    [ q{perl -le 'print "l adds the newline"'}, "-l appends a newline to print" ],
    [ q{perl -e 'print 2**10, "\n"'},           "any expression at all" ],
);

for my $d (@demo) {
    my ($cmd, $why) = @$d;
    my $out = `$cmd 2>&1`;
    $out =~ s/\s+\z//;
    printf "%-46s -> %-24s (%s)\n", $cmd, "[$out]", $why;
}

# and the exit status works exactly as Chapter 15.4 described
system(q{perl -e 'exit 3'});
printf "\nperl -e 'exit 3'  -> exit status %d\n", $? >> 8;
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
perl -e 'print "hello\n"'                      -> [hello]                  (the simplest form)
perl -e 'my $x = 6;' -e 'print $x*7, "\n"'     -> [42]                     (two -e options, one program)
perl -E 'say "say needs -E"'                   -> [say needs -E]           (-E switches on modern features)
perl -le 'print "l adds the newline"'          -> [l adds the newline]     (-l appends a newline to print)
perl -e 'print 2**10, "\n"'                    -> [1024]                   (any expression at all)

perl -e 'exit 3'  -> exit status 3

Two results from that worth naming:

Several -e options are joined into one program. The second row sets $x in the first -e and uses it in the second. Perl concatenates them with newlines between, so it is one script, not two. That is how you keep a slightly longer one-liner readable.

-E is -e plus modern features, which in practice means say. Plain perl -e 'say "x"' is a syntax error — String found where operator expected ... Do you need to predeclare say? — because say is a feature that must be enabled. Use -E and it works.

2. The Flags Worth Knowing

A handful of single letters do most of the work. They combine, so perl -lane is -l -a -n -e.

FlagDoes
-ethe program text follows
-Esame, with modern features on (say)
-lstrip the newline on input, add one to every print
-nwrap the program in a loop over every input line
-pthe same loop, and print $_ at the end of each pass
-asplit each line into @F
-Fchoose the separator -a splits on
-iedit the input files in place
-wwarnings on
-Mload a module, as in -MList::Util=sum

-n, -p, -a, -F and -i get their own chapters next, because each has behaviour worth measuring. The two to understand now are -l and -M.

-l does two things at once. It chomps each input line, and it adds $/ — a newline — to everything print outputs. So perl -lne 'print length($_)' measures the line without its newline and prints the number on its own line. Without -l, the length is one larger and the numbers run together.

-M loads a module and can import from it:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
perl -MList::Util=sum,max -lane 'push @s, $F[1]; END { print sum(@s), " ", max(@s) }' slack.txt

List::Util is core, so that works anywhere. -MPOSIX, -MData::Dumper and -MFile::Basename are the other three you will reach for, all from Chapter 12.9's list.

3. Quoting: The Shell Reads It First

This is the only genuinely confusing part of one-liners, and it has nothing to do with Perl.

Azvya Education Pvt. Ltd.VLSI Mentor
quoting.pl
use strict;
use warnings;

# the SAME program text, quoted two ways for the shell
my $perl_program = 'my $x = "PERL"; print "x is [$x]\n"';

my $single = `perl -e '$perl_program' 2>&1`;

# build the double-quoted form the way a user would type it
my $dq = '"' . $perl_program . '"';
my $double = `perl -e $dq 2>&1`;

for ($single, $double) { s/\s+\z//; s/\n/ | /g }

print "the program text:\n  $perl_program\n\n";
printf "in SINGLE quotes -> %s\n", "[$single]";
printf "in DOUBLE quotes -> %s\n", "[$double]";
print "\nthe shell expanded \$x before Perl saw it, so the program changed\n";
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
the program text:
  my $x = "PERL"; print "x is [$x]\n"

in SINGLE quotes -> [x is [PERL]]
in DOUBLE quotes -> [syntax error at -e line 1, near "my  =" | Execution of -e aborted due to compilation errors.]

the shell expanded $x before Perl saw it, so the program changed

The same characters, two results. In double quotes the shell found $x, decided it was a shell variable, found it empty, and replaced it with nothing — handing Perl my = "PERL", which is not valid Perl at all.

That syntax error is the lucky outcome. It is loud, and you fix it immediately. The same expansion can just as easily produce a program that still compiles and quietly computes something else: perl -e "print $total" becomes print and prints $_, and perl -e "print 1 if $x > 5" becomes print 1 if > 5 — a different question with a believable answer. Chapter 14.1's third kind of failure, caused by a quote character.

The rules on a POSIX shell (sh, bash, zsh):

Single quotes pass everything through untouched. $, !, \, backticks — Perl receives exactly what you typed. This is what you want, essentially always.

Double quotes let the shell expand $name, backticks and \ before Perl sees them. Useful only when you deliberately want a shell value substituted into the program, which is rarely a good idea.

A single quote inside a single-quoted program needs care. You cannot escape it inside single quotes. The usual answer is to avoid apostrophes entirely, or close and reopen:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
perl -e 'print "it'\''s awkward\n"'      # close, escaped quote, reopen
perl -e "print \"it's easier\n\""        # or use double quotes deliberately

Better than either: when a program needs quotes of both kinds, that is the signal it has outgrown the command line.

4. When To Stop

A one-liner is the right tool for a job you will do once. The signals that you have passed that point:

You have typed it more than twice. Put it in a file. The third time is the one where you misremember a detail and get a wrong answer that looks right.

It needs more than two -e fragments, or any if you have to think about. Command lines have no indentation, no comments and no way to leave a note for the next person.

You want to keep the output. Something a colleague will read should come from a file you can point at, not from a shell history nobody else has.

It needs quotes of both kinds. As above — the escaping cost has exceeded the saving.

Promoting a one-liner to a file is mechanical. This:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
perl -lane 'print "$F[0] $F[1]" if $F[1] < 0' slack.txt

becomes this, with the implicit parts written out:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
#!/usr/bin/perl
use strict;
use warnings;

while (my $line = <>) {              # what -n provided
    chomp $line;                     # what -l provided
    my @F = split ' ', $line;        # what -a provided
    next unless @F >= 2;             # a check the one-liner could not afford
    print "$F[0] $F[1]\n" if $F[1] < 0;
}

Longer, and better in every way that matters once it is going to be run again: it has a name, it can be commented, it can check its input, and Chapter 15.3's validation can be added to it.

Chapter 15.7 writes out exactly what -n and -p expand to, using Perl's own deparser rather than a description — which makes the translation above something you can verify instead of trusting.

5. What To Remember

  • perl -e 'PROGRAM' runs a whole program with no file, and nothing is cut down.
  • Several -e options join into one program. Measured: $x set in the first was used in the second.
  • -E enables modern features; plain -e with say is a syntax error — measured.
  • -l chomps input and adds a newline to every print.
  • -M loads a module — -MList::Util=sum,max and -MPOSIX are the common ones.
  • -w while building, so a silently-zero value does not become an answer you trust.
  • Flags combine: -lane is -l -a -n -e.
  • Single-quote the program. Measured: in double quotes the shell expanded $x to nothing and Perl ran a different program.
  • Double quotes expand $name, backticks and \ before Perl sees them.
  • A ! in double quotes can trigger history expansion at an interactive prompt.
  • Forgetting the quotes makes Perl seem to hang — it is reading your terminal as a file.
  • Stop at the third use, at two -e fragments, at any real if, or at needing both quote kinds.
  • Promotion is mechanical: -n becomes the while loop, -l becomes chomp, -a becomes split.

Chapter 15.7 takes the two flags that make one-liners genuinely powerful. -n and -p wrap your code in a reading loop, and Perl will show you the exact loop it generates.

Where this fits

Part of the Perl curriculum.