Beginner

Operators in Perl

Learn arithmetic, string, comparison, logical, and assignment operators in Perl, including the distinct numeric and string comparison families.

Operators are the building blocks of every expression you’ll write in Perl. Because Perl is dynamically typed with weak conversions between numbers and strings, it takes a route no other mainstream language matches: it gives you two parallel families of comparison operators — one for numbers (==, <, >, <=>) and one for strings (eq, lt, gt, cmp). The operator itself decides which type the operands should be coerced to, not the values.

This design eliminates a whole class of bugs that plague languages like JavaScript, where "10" < "9" evaluates differently depending on operand types. In Perl, you state your intent through the operator you pick. Combined with sigil-tagged variables and a rich set of string operators (., x, =~), Perl’s operator vocabulary reflects its origins as a text-processing language.

This tutorial covers arithmetic, string, comparison, logical, assignment, and a handful of distinctively Perl operators like the repetition operator x, the defined-or operator //, and the binding operator =~.

Arithmetic and String Operators

Perl’s arithmetic operators look familiar, but it also ships dedicated string operators: . for concatenation and x for repetition. Mixing them with weak typing produces some interesting results.

Create a file named operators_arith.pl:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';

# --- Arithmetic operators ---
my $a = 17;
my $b = 5;

say "a + b  = ", $a + $b;     # Addition
say "a - b  = ", $a - $b;     # Subtraction
say "a * b  = ", $a * $b;     # Multiplication
say "a / b  = ", $a / $b;     # Division (always floating point)
say "a % b  = ", $a % $b;     # Modulus (integer remainder)
say "a ** b = ", $a ** $b;    # Exponentiation
say "int(a/b) = ", int($a / $b);  # Truncated integer division

# --- String operators ---
my $greeting = "Hello";
my $target   = "World";

say $greeting . ", " . $target . "!";  # Concatenation with .
say "-" x 20;                          # Repetition: 20 dashes
say "ha" x 3;                          # "hahaha"

# --- Weak typing: numeric strings coerce automatically ---
my $num_str = "42";
say "'42' + 8 = ", $num_str + 8;       # 50 (string used as number)
say "'42' . 8 = ", $num_str . 8;       # "428" (number used as string)

# --- Non-numeric strings coerce to 0 in numeric context ---
my $word = "abc";
say "'abc' + 1 = ", $word + 1;         # 1 (with no 'use warnings' it's silent)

Note: under use warnings;, coercing "abc" to a number raises a warning. The line is included to show the behavior, not to encourage it.

Comparison Operators: Numeric vs. String

This is the section that trips up newcomers from other languages. Perl has two complete sets of comparison operators. Pick the one that matches what you’re comparing.

ComparisonNumericString
Equal==eq
Not equal!=ne
Less than<lt
Greater than>gt
Less or equal<=le
Greater or equal>=ge
Three-way (sort)<=>cmp

The three-way operators (<=> and cmp) return -1, 0, or 1 — perfect for sort.

Create a file named operators_cmp.pl:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';

# --- Numeric vs string comparison: same operands, different results ---
my $x = "10";
my $y = "9";

say "10 == 9? ", ($x == $y ? "yes" : "no");   # Numeric: 10 != 9
say "10 eq 9? ", ($x eq $y ? "yes" : "no");   # String:  "10" ne "9"
say "10 <  9? ", ($x <  $y ? "yes" : "no");   # Numeric: 10 is NOT < 9
say "10 lt 9? ", ($x lt $y ? "yes" : "no");   # String:  "10" IS < "9" lexically

# --- Three-way comparison returns -1, 0, or 1 ---
say "5 <=> 10 = ", 5 <=> 10;
say "5 <=> 5  = ", 5 <=> 5;
say "5 <=> 1  = ", 5 <=> 1;

# Useful for sorting:
my @numbers = (10, 2, 33, 4, 25);
my @sorted_num = sort { $a <=> $b } @numbers;   # Numeric sort
my @sorted_str = sort { $a cmp $b } @numbers;   # String sort

say "Numeric sort: @sorted_num";
say "String  sort: @sorted_str";

The string sort places 10 before 2 because "1" comes before "2" lexicographically — exactly the bug a naive sort produces in many languages.

Logical, Assignment, and Distinctly Perl Operators

Perl’s logical operators come in two flavors: the C-style symbols (&&, ||, !) and lower-precedence word forms (and, or, not). The word forms are typically used for control flow at statement level (open(FH, $f) or die "..."), while the symbol forms are used inside expressions.

Perl also offers the defined-or operator //, which only falls back when the left side is undef (not merely false), and the binding operator =~ that ties a value to a regex.

Create a file named operators_logic.pl:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';

# --- Short-circuit logical operators return the deciding operand ---
my $a = 0;
my $b = "fallback";
say "a || b = ", $a || $b;    # 0 is false -> "fallback"
say "a && b = ", $a && $b;    # 0 is false -> 0 (short-circuits)

# --- || vs //: the defined-or operator ---
my $maybe_zero = 0;
my $undefined;

say "0  || 'x' = ", ($maybe_zero || 'x');   # 'x'  (0 is falsy)
say "0  // 'x' = ", ($maybe_zero // 'x');   # 0   (only undef triggers fallback)
say "u  // 'x' = ", ($undefined  // 'x');   # 'x'

# --- Assignment operators (compound forms) ---
my $n = 10;
$n += 5;    say "after += 5  : $n";   # 15
$n -= 3;    say "after -= 3  : $n";   # 12
$n *= 2;    say "after *= 2  : $n";   # 24
$n **= 2;   say "after **= 2 : $n";   # 576

my $s = "log";
$s .= "-entry";   say "after .= : $s";    # "log-entry"
$s x= 2;          say "after x= 2: $s";   # "log-entrylog-entry"

# --- Binding operator =~ ties a value to a regex ---
my $text = "Perl 5.40 was released in 2024";
if ($text =~ /(\d{4})/) {
    say "Found year: $1";
}

(my $shouted = $text) =~ s/perl/PERL/i;
say $shouted;

# --- Range operator .. (in list context, produces a list) ---
my @one_to_five = (1..5);
say "Range 1..5: @one_to_five";

Note that Perl uses # for comments — there are no // line comments. The // token always means the defined-or operator (or an empty regex), depending on context.

Running with Docker

1
2
3
4
5
6
7
# Pull the official Perl image
docker pull perl:5.40-slim

# Run each example
docker run --rm -v $(pwd):/app -w /app perl:5.40-slim perl operators_arith.pl
docker run --rm -v $(pwd):/app -w /app perl:5.40-slim perl operators_cmp.pl
docker run --rm -v $(pwd):/app -w /app perl:5.40-slim perl operators_logic.pl

Expected Output

Output of operators_arith.pl:

a + b  = 22
a - b  = 12
a * b  = 85
a / b  = 3.4
a % b  = 2
a ** b = 1419857
int(a/b) = 3
Hello, World!
--------------------
hahaha
'42' + 8 = 50
'42' . 8 = 428
'abc' + 1 = 1

Output of operators_cmp.pl:

10 == 9? no
10 eq 9? no
10 <  9? no
10 lt 9? yes
5 <=> 10 = -1
5 <=> 5  = 0
5 <=> 1  = 1
Numeric sort: 2 4 10 25 33
String  sort: 10 2 25 33 4

Output of operators_logic.pl:

a || b = fallback
a && b = 0
0  || 'x' = x
0  // 'x' = 0
u  // 'x' = x
after += 5  : 15
after -= 3  : 12
after *= 2  : 24
after **= 2 : 576
after .= : log-entry
after x= 2: log-entrylog-entry
Found year: 2024
PERL 5.40 was released in 2024
Range 1..5: 1 2 3 4 5

Key Concepts

  • Two comparison families: ==/</> work on numbers; eq/lt/gt work on strings. The operator decides the coercion, not the operands.
  • String operators are first-class: . concatenates, x repeats — they aren’t overloaded + and * as in many languages.
  • Three-way operators (<=> for numbers, cmp for strings) return -1, 0, or 1 and are the idiomatic way to build custom sort comparators.
  • Defined-or // is the safe fallback: it only triggers on undef, unlike || which fires for any falsy value (including 0 and "").
  • Compound assignment works for every binary operator, including the string-specific ones — .= appends, x= repeats in place.
  • The binding operator =~ is what makes regex feel built-in: it attaches a string to a m// match or s/// substitution.
  • Word-form logicals (and, or, not) have very low precedence — ideal for statement-level flow control like open($fh, $f) or die, but use the symbol forms inside expressions.
  • Weak typing means silent coercion: a non-numeric string used in arithmetic becomes 0 (with a warning under use warnings), so always pick the operator family that matches your intent.

Running Today

All examples can be run using Docker:

docker pull perl:5.40-slim
Last updated:

Comments

Loading comments...

Leave a Comment

2000 characters remaining