Home / Alt manpages / perldata(1)

  • perldata(1)
  • User command
  • linux

Perl Data Types: Use Scalars, Arrays and Hashes Without Guesswork

You will finish with a small Perl program that uses a scalar, an array and a hash, then checks their values without relying on Perl's easy-to-miss context rules. Allow about 20 minutes. You need Perl installed and a shell; no administrator access is required. The examples below were run with Perl 5.38.2, the version installed on this machine.

1. Check the interpreter

Start by confirming which Perl you will run. This matters when a script is moved between distributions or machines, because the manual page describes the installed interpreter's language details.

$ perl -v
This is perl 5, version 38, subversion 2 (v5.38.2) built for x86_64-linux-gnu-thread-multi

The perldata(1) manual identifies three built-in data types: scalars, arrays of scalars, and hashes of scalars. A scalar can hold a string, number or reference. Perl converts between string and numeric uses when an operation asks for one, so the variable declaration does not permanently fix a scalar's type.

2. Give each variable the right sigil

The first character tells Perl whether an expression produces one value or several. Use $ for one scalar, @ for an array, and % for a hash. A useful source of confusion is that an individual array or hash element is a scalar, so it uses $ even though the container uses @ or %.

use strict;
use warnings;

my $host = 'server-a';
my @ports = (22, 443, 8080);
my %labels = (
    22   => 'ssh',
    443  => 'https',
    8080 => 'application',
);

print "$host has $ports[0] open for $labels{22}\n";

The array starts at index 0, so $ports[0] is 22. The hash is addressed by a string key, and $labels{22} returns the value for that key. The same name can legally exist in different namespaces, so $item, @item and %item are separate variables. Names are case-sensitive.

Save that as /tmp/perldata-demo.pl and run it:

$ perl /tmp/perldata-demo.pl
server-a has 22 open for ssh

Checkpoint: if the output differs, inspect the sigils and the zero-based index before changing anything else.

3. Keep list and scalar context separate

Perl gives an expression either list context or scalar context. List context asks for multiple values; scalar context asks for one. Assignment supplies context from its left side: assigning to an array evaluates the right side as a list, while assigning to a scalar evaluates it as a scalar.

my @words = qw(red green blue);
my $count = scalar @words;
my ($first, $second) = @words;

printf "count=%d first=%s second=%s\n", $count, $first, $second;

Here scalar @words makes the intent explicit and produces the array length. In scalar context, an array also evaluates to its length. Do not confuse that with $#words: it is the last valid index, so an array with three elements has length 3 but last index 2. Assigning a smaller value to $#words removes elements, which is a state change rather than a harmless query.

A list assignment can leave a variable undefined if the right side is too short. Check that case with defined rather than treating an empty string as equivalent:

Save this short example as /tmp/perldata-context.pl before running it:

my ($name, $role) = ('Ada');
print defined($role) ? "role=$role\n" : "role is undefined\n";
$ perl /tmp/perldata-context.pl
role is undefined

This distinction matters when an absent value and a deliberately empty value have different meanings. An undefined scalar, an empty string, numeric zero and the string "0" are false in Boolean context. Other values, including most non-empty strings, are true.

4. Interpolate strings deliberately

Double-quoted strings interpolate scalar and array values and process backslash escapes. Single-quoted strings do neither, apart from the special handling of a single quote and backslash. Braces prevent a variable name from running into nearby text or being parsed as an array or hash access.

my $user = 'Ada';
my @files = ('report.txt', 'summary.txt');

print "${user}'s files: @files\n";
print 'Literal $user and literal \n text\n';

Without braces, "$user's" can be parsed as a package-qualified variable rather than the word you intended. Likewise, text immediately following a scalar can look like an index. Prefer "${user}s" when the boundary is not obvious. Hashes do not interpolate as a useful key/value display; format the keys explicitly when output order matters.

5. Read and update elements safely

Use square brackets for array subscripts and curly brackets for hash subscripts. Negative array indices count backwards, so $ports[-1] is the last element. A missing hash key returns an undefined scalar. Test presence with exists when a stored false value, such as zero, is still a real entry.

if (exists $labels{0}) {
    print "port 0 is labelled\n";
} else {
    print "port 0 has no label\n";
}

$labels{80} = 'http';
print "last port=$ports[-1]\n";

Do not assume that a hash will return keys in insertion order. Hashes are unordered collections in the data model described by perldata(1). If stable output is required, retrieve and sort the keys:

for my $port (sort { $a <=> $b } keys %labels) {
    print "$port=$labels{$port}\n";
}

For a read-only inspection, run the program normally. Do not use sudo: Perl data structures live in the process, and elevated privileges only increase the damage a faulty script could do to the filesystem or services.

6. Verify the complete example

Run Perl's syntax check before executing a script you have edited. The -c option checks compilation without running the program:

$ perl -c /tmp/perldata-demo.pl
/tmp/perldata-demo.pl syntax OK
$ perl /tmp/perldata-demo.pl
server-a has 22 open for ssh

Keep use strict and use warnings in ordinary scripts. They catch misspelled variable names and report many accidental uses of undefined values. They do not replace tests: a syntactically valid program can still use the wrong key or an unintended context.

Done means

  • You can identify $, @ and % from the number of values an expression represents.
  • You use scalar @array for a clear length query and distinguish it from $#array, the last index.
  • You check defined and exists when missing data must differ from empty or false data.
  • You use braces for ambiguous interpolation and sort hash keys when output needs a stable order.
  • perl -c reports syntax OK, and the script runs without elevated privileges.