ここではPerlの変数とデータ構造についての基本的な事項を学びます。応用的な事項についてはリファレンスで触れます。
Perlでは、変数は「データを格納する領域（オブジェクト）に付けられた名前」です。
同じオブジェクトを２つ以上の変数が指し示すこともありますし、配列の要素のように、単体では名前がないオブジェクトもあります。
変数を用いることにより、データをより柔軟に扱うことができます。
変数の利用の形態は大きく分けて宣言、代入、参照の3種です。
Perlには3つの組み込みデータ型があります。
スカラー
配列:カラーを0から始まる番号でインデックス付けした順序付きコレクション
ハッシュ:スカラー値を関連する文字列キーでインデックス付けした順序付きでないコレクション
変数のデータ型は、接頭辞（ ''sigil'' ; シジル）によって区別します。
スカラーは、内部に構造をもたない「ただ一つ」の値を保持できるデータ型で、接頭辞は、$（ドルマーク；Scalar の S）です。
[https://paiza.io/projects/2OElPALIaRY3LNpTYwho7g?language=perl 例]:
use v5.12;
use warnings;
my $name = "太郎";# レキシカル変数 $name を "太郎" で初期化
my $age = 30;     # レキシカル変数 $age を 30 で初期化
say $name;
say $age;
実行結果:
太郎
30
スカラー変数の接頭辞は、$（ドルマーク；Scalar の S）です。
数学では「スカラー」の対義語は「ベクトル」ですが、Perlでは、「リスト」が「スカラー」の対義語です。
数学的にはしっくりきませんが、文字列もスカラーです。
変数が示している値が数値か文字列かは、値側にある情報「型」により決まります。
上記コードでは、「name」という名称のスカラー変数 $name と、「age」という名称のスカラー変数 $age があります。
スカラー変数 $age は、数値（整数） 30 を保持します。
このように、一つの変数は、単一の値を保持できます。
文字列リテラル:”ABC and Z” や 'ABC and Z'のように、”（ダブルクォーテーションマーク）や’（シングルクォーテーションマーク）で囲みます。
数値:”や’囲む必要はありませんが、囲んでも実行時に数値として解釈されます。また、NaN や Inf のような特殊な値は、”や’囲む必要があります。
[A-Za-z_][A-Za-z_0-9]{0,250}
不正な識別子の例:
123age
new-word
フラッグ
Perlは、演算子式を評価するに当たり、演算子ごとにオペランドの型を強制的に変換します。
[https://paiza.io/projects/h3XUo9yP3z96UFLePJjLfQ?language=perl 例]:
use v5.12;
use warnings;
my $age = 30;       say __LINE__ . ": $age";
$age = $age . "1";  say __LINE__ . ": $age";
$age = $age + 1;    say __LINE__ . ": $age";
$age = $age x 3;    say __LINE__ . ": $age";
$age = $age / 302;  say __LINE__ . ": $age";
実行結果:
5: 30
6: 301
7: 302
8: 302302302 
9: 1001001
このように、演算子によってオペランドが数値と解釈されたり文字列と解釈されたりします。
逆に言うと、演算子を見ればオペランド（と式の値）の型がわかります。
次のプログラムは、等価な代入演算子による実装です。
[https://paiza.io/projects/w5aDaniOTJwoq-51B50UDQ?language=perl 例]:
use v5.12;
use warnings;
my $age = 30;   say __LINE__ . ": $age";
$age .= "1";    say __LINE__ . ": $age";
$age += 1;      say __LINE__ . ": $age";
$age x= 3;      say __LINE__ . ": $age";
$age /= 302;    say __LINE__ . ": $age";
実行結果:
5: 30
6: 301
7: 302
8: 302302302 
9: 1001001
例外的に、インクリメント演算子は数値にも文字列にも作用します。
[https://paiza.io/projects/8y9G_F_piLGJyifRhOEDeA?language=perl 例]:
use v5.12;
use warnings;
my $n = 3;  say __LINE__ . ": $n";
$n++;       say __LINE__ . ": $n";
$n++;       say __LINE__ . ": $n";
my $s = "K";say __LINE__ . ": $s";
$s++;       say __LINE__ . ": $s";
$s++;       say __LINE__ . ": $s";
$s = "BY";  say __LINE__ . ": $s";
$s++;       say __LINE__ . ": $s";
$s++;       say __LINE__ . ": $s";
$s++;       say __LINE__ . ": $s";
実行結果:
5: 3
6: 4
7: 5
9: K
10: L
11: M
13: BY
14: BZ
15: CA 
16: CB
このような文字列をオペランドに取ったときのインクリメントをマジカルインクリメントと呼びます。
{{コラム|ほかのプログラミング言語との違い|2=C/C++と違いPerlでは変数宣言でに、int や double などの型を指定することはありません。
Perlでは、スカラー変数に整数・浮動小数点数・文字列やリファレンスの間で暗黙の変換が働くからです。
レキシカルスコープのスカラー変数の宣言:
my $変数名 = 初期値;
例えば、print 関数の引数に整数が渡されれば、自動的に十進数の文字列に変換されます。
このように、演算子・関数・サブルーチンやメソッドが適宜変換します。
これは、Perlが参考にしたAWKと同じ特徴です。
また、Perlで「データ型」というと
などのことで、接頭辞などで区別されます。
配列はスカラーの集合で、整数のインデックスでそれぞれの要素スカラーを参照できるデータ型で、接頭辞は、@（アットマーク；array の a）です。
[https://paiza.io/projects/sNyDvYypxngMQChjKmzQTw?language=perl 例]:
use v5.12;
use warnings;
my @ary = ("太郎", 30);            # 配列変数 @ary を、リスト ("太郎" 30) で初期化
say __LINE__ . ": $ary[0]";        # 配列変数 @ary の 0 番目の要素を参照
say __LINE__ . ": $ary[1]";        # 配列変数 @ary の 1 番目の要素を参照
say __LINE__ . ": $ary[-1]";       # 配列変数 @ary の -1 番目（最後）の要素を参照
say __LINE__ . ": $ary[-2]";       # 配列変数 @ary の -1 番目（最後から 2 番目）の要素を参照
say @ary;                          # そのまま文字列化すると、要素を文字列化したものを区切り文字なく連結
{ local $, = ";" ; say @ary; }     # {} でスコープを切って local で区切り文字グローバル変数 $, をローカライズしたので
say @ary;                          # スコープを抜けると元通り
say __LINE__ . ": \@ary = @ary";   # 文字列中で展開すると、区切り文字は１文字の空白
say __LINE__ . ": \@ary = @{[@ary]}";# ベビーカー演算子 @{[式]} でも同じ
$ary[1] = 25;                      # １番めの要素に 25 を代入
say __LINE__ . ": \@ary = @ary";   # 置換わる
$ary[1]++;                         # インクリメント
say __LINE__ . ": \@ary = @ary";   # 増える
$ary[1] = "ABC";                   # １番めの要素に "ABC" を代入
say __LINE__ . ": \@ary = @ary";   # 置換わる
$ary[1]++;                         # インクリメント
say __LINE__ . ": \@ary = @ary";   # 増える！
push @ary, "XYZ";                  # push は配列の末尾に追加
say __LINE__ . ": \@ary = @ary";   # 増える（違う意味で）
unshift @ary, "UVW";               # unshift は配列の先頭に追加
say __LINE__ . ": \@ary = @ary";   # 増える（また違う意味で）
my $x = shift @ary;                # shift は先頭要素の取出し
say __LINE__ . ": $x";             #   戻値は取出した値
say __LINE__ . ": \@ary = @ary";   # 先頭がなくなった
my $y = pop @ary;                  # pop は末尾要素の取出し
say $y;                            #   戻値は取出した値
say __LINE__ . ": \@ary = @ary";   # 末尾がなくなった
my $z = @ary;                      # スカラ変数へ配列変数を代入すると
say __LINE__ . ": \$z = $z";       # 要素数が入る
push @ary, qw(A B C D);            # リストをpush（qw/STRING/の例）
say __LINE__ . ": \@ary = @ary";   # 展開されて追加される
foreach my $el(@ary) {  # foreach ループは先頭から順位要素にブロックを適用
  say __LINE__ . ": \$el = $el";
}
foreach (@ary) {        # ループ変数を宣言しなくても $_ で要素を参照できる
  say __LINE__ . ": \$_ = $_";
}
say __LINE__ . ": \$_ = $_" foreach (@ary); # 同じ意味
実行結果:
7: 太郎
8: 30
9: 30
10: 太郎
太郎30
太郎;30
太郎30
16: @ary = 太郎 30
17: @ary = 太郎 30
20: @ary = 太郎 25
23: @ary = 太郎 26
26: @ary = 太郎 ABC
29: @ary = 太郎 ABD
32: @ary = 太郎 ABD XYZ
35: @ary = UVW 太郎 ABD XYZ
38: UVW
39: @ary = 太郎 ABD XYZ
XYZ
43: @ary = 太郎 ABD
46: $z = 2
49: @ary = 太郎 ABD A B C D
52: $el = 太郎
52: $el = ABD
52: $el = A
52: $el = B
52: $el = C
52: $el = D
56: $_ = 太郎
56: $_ = ABD
56: $_ = A
56: $_ = B
56: $_ = C
56: $_ = D
59: $_ = 太郎
59: $_ = ABD
59: $_ = A
59: $_ = B
59: $_ = C 
59: $_ = D
接頭辞は、@（アットマーク；array の a）です。
配列の要素にはスカラーが入り、１つの配列に文字列や数値やリファレンスが混在することができます。
[https://paiza.io/projects/p8KNkM1toBAaE-FDrQB-Yg?language=perl 例]:
use v5.30.0;
use warnings;
my @x = 1..10;
say __LINE__ . ":\@x --> @x";
my @y = @x;
say __LINE__ . ":\@y --> @y";
$y[$_] *= 2 foreach (0..$#y);
say __LINE__ . ":\@x --> @x";
say __LINE__ . ":\@y --> @y";
実行結果:
6:@x --> 1 2 3 4 5 6 7 8 9 10
9:@y --> 1 2 3 4 5 6 7 8 9 10
12:@x --> 1 2 3 4 5 6 7 8 9 10
13:@y --> 2 4 6 8 10 12 14 16 18 20
Perlで、配列変数同士のコピーは、全ての要素の一対一の複製です。
当たり前のようですが、動的型付けの言語の中では、意外と少数派です。
[https://paiza.io/projects/XtC3FJgpWRmvjsDT7XZ5xQ?language=ruby Rubyの例]:
x = Array(1..10)
puts "#{__LINE__}:x --> #{x}"
y = x
puts "#{__LINE__}:y --> #{y}"
y.map!
Perlの数値は、内部的にはネイティブな整数・ネイティブな浮動小数点数・数値を示す文字列で記憶します。
数値リテラルは、10進数、2進数（0bを前置）, 8進数（0あるいは0oを前置）, 16進数（0xを前置）によって数値を表現できます。
また、指数表現も可能です。
[https://www.mycompiler.io/view/IstR4leXqMQ 例]:
use v5.34;
use warnings;
print < @{[ 42 ]}
0b1101\t--> @{[ 0b1101 ]}
0177\t--> @{[ 0177 ]}
0o333\t--> @{[ 0o333 ]}
0xff\t--> @{[ 0xff ]}
3.14\t--> @{[ 3.14 ]}
5.00e3\t--> @{[ 5e3 ]}
EOS
実行結果:
42	--> 42
0b1101	--> 13
0177	--> 127
0o333	--> 219
0xff	--> 255
3.14	--> 3.14 
5.00e3	--> 5000
Perlは、数値としての非数(NaN)と無限大(Inf)をサポートしています。
ただし、大概のNaNやInfが返りそうな演算では例外が上がって来ますし、数値リテラルとしての NaN や Inf はなく、"NaN" と "Inf" をつかいます。
このとき、大文字小文字を問わず単純な先頭一致なので、以下のような少し面倒な状況がおこります。
[https://paiza.io/projects/D2Oj39_YCmTg8PB9fTj7Qw?language=perl 例]:
use v5.30.0;    # v5.12 以降は use strict の機能を含んでいます。
use warnings;
eval { my $x = 1.0/0.0 }; # JavaScript, Ruby では無限大がかえる
warn $@ if $@;            # Perl では、Illegal division by zero
eval { my $x = 0.0/0.0 }; # JavaScript, Ruby では非数がかえる
warn $@ if $@;            # Perl では、Illegal division by zero
say 0+"information";
say 0+"nano";
my $huge = 10**1010;
say $huge;
say -$huge;
say $huge - $huge;
実行時の警告:
Illegal division by zero at Main.pl line 4.
Illegal division by zero at Main.pl line 7.
Argument "information" isn't numeric in addition (+) at Main.pl line 10. 
Argument "nano" isn't numeric in addition (+) at Main.pl line 11.
実行結果:
Inf
NaN
Inf
-Inf 
NaN
数値としての無限大は ”Inf” に、非数は ”NaN” に正規化されます。
単純な文字列から数値への変換（Perlが常々行う暗黙の強制変換でも）無限大や非数に転んでしまう危うさあることを示しています。
変数 $n があるとき、 $n != $n が真なら NaN、abs($n) == "Inf" が真なら Inf または -Inf です。
Perlに限らず、数値計算には誤差が伴います。
例えば、0.01 を 100 回足しても 1 にはなりません。
これを保証する方法はいくつかありますが、ここではカハンの加算アルゴリズムを紹介します。
[https://paiza.io/projects/D2Oj39_YCmTg8PB9fTj7Qw?language=perl 例]:
use v5.30;    # v5.12 以降は use strict の機能を含んでいます。
use warnings;
my ( $delta, $iter ) = ( 0.01, 100 );
my $sum = 0.0;
$sum += $delta foreach ( 1 .. $iter );
say sprintf "素朴な実装:\t\t%.55f", $sum;
$sum = 0;
my $c = 0;
foreach ( 1 .. $iter ) {
    my $y = $delta - $c;
    my $t = $sum + $y;
    $c   = ( $t - $sum ) - $y;
    $sum = $t;
}
say sprintf "カハンの加算アルゴリズム:\t%.55f", $sum;
use List::Util qw(sum);
my @v;
push @v, $delta foreach ( 1 .. $iter );
say sprintf "List::Util::sum:\t%.55f", List::Util::sum @v;
実行結果:
素朴な実装:		1.0000000000000006661338147750939242541790008544921875000
カハンの加算アルゴリズム:	1.0000000000000000000000000000000000000000000000000000000 
List::Util::sum:	1.0000000000000006661338147750939242541790008544921875000
List::Utilモジュールのsumが、素朴な実装と同じ値というのはいがいでした。
プログラマーが変数を宣言しなくても、いくつかの変数は機能が決まっていて、事前にPerlに用意されており、このような変数を特殊変数あるいは処理系定義済み変数と言います。
たとえば特殊変数 $0 は、プログラム名が代入されています。
[https://paiza.io/projects/M_V-0hGHWrCeTZn4CAU_Fg?language=perl 例]:
use v5.12; # v5.12 は use strict の機能を含んでいます。
use warnings;
say $0;
say `ps -x`;
$0 = "(secret)";
say $0;
say `ps -x`;
実行結果:
Main.pl
    PID TTY      STAT   TIME COMMAND
     10 ?        S      0:00 /bin/sh ./exec_command
     11 ?        S      0:00 perl Main.pl
     12 ?        R      0:00 ps -x
(secret)
    PID TTY      STAT   TIME COMMAND
     10 ?        S      0:00 /bin/sh ./exec_command
     11 ?        S      0:00 (secret)
     13 ?        R      0:00 ps -x
$0 は、値を参照するだけでなく上書きすることもできます。
値を上書きすると、Perlのスクリプトから参照できる値が変わるだけでなく、環境も書換えます。
[https://paiza.io/projects/D2p_VZ75c-QrePGlXzyFkg?language=perl 例]:
use v5.12; # v5.12 は use strict の機能を含んでいます。
use warnings;
print <
実行結果:
$^O: linux	-- OS名
$^T: 1668142037	-- プロセスの開始時刻（エポックからの通算秒）
$^V: v5.30.0	-- perl インタープリターバージョン 
$$: 11	-- Process ID
変数、関数、定数などが、式の中でどのように評価されるか決定するものです。
大別するとスカラー・コンテキストとリスト・コンテキストがあり、スカラー・コンテキストにおかれた値はスカラーとして、リスト・コンテキストにおかれた値はリストとして評価されます。
コンテキストと実際のデータが食い違っている場合、次のような規則で評価されます。
スカラー・コンテキストにリストがおかれた場合、リストの最後の要素が評価されます（コンマ演算子の為）。
リスト・コンテキストにスカラーがおかれた場合、そのスカラー1個だけを要素とするリストであると解釈されます。
どのようにコンテキストが提供されるか、以下にいくつか例を示します。
代入式は右辺に、左辺と同じコンテキストを提供します：
[https://paiza.io/projects/-1wL6n-2U8mVA779Za8svw?language=perl コード例]:
my @array = qw(Foo Bar Baz);
my $var = @array;
print $var
実行結果:
3
qw は、つづく丸カッコ内をスペースで区切ってリスト化する演算子です。
配列はスカラー・コンテキストで評価されるとその要素数を返すので、結果として$numberには3が代入されます。
ただしこのような結果になるのは配列だけです。
前述したとおり、リストがスカラー・コンテキストで評価されると、最後の要素が返されます：
[https://paiza.io/projects/RjdQUDGdP17kuN2nMeYSWA?language=perl コード例]:
my $var = qw(Foo Bar Baz);
my ($foo, $bar, $baz) = 'Foo';
print <
実行結果:
Baz 
(Foo), (), ()
右辺はスカラーですが、左辺がリスト値を期待している為、1つの要素'Foo'のみを持つリストと解釈されます。
これが $foo に代入されますが、残りの2つの変数については、対応する右辺値がない為未定義となります。
したがって、これは次のコードと等価です：
my ($foo, $bar, $baz) = ('Foo', undef, undef);
フォワード宣言されたサブルーチンは、デフォルトで引数にリスト・コンテキストを提供します：
sub user_func;
user_func 'foo', 'bar', 'baz';
これは次のように解釈されます。
user_func('foo', 'bar', 'baz');
つまり、括弧のないサブルーチン呼び出しはリスト演算子として扱われます。
もしこれを、
user_func('foo'), 'bar', 'baz'
と解釈させたいのなら、フォワード宣言にプロトタイプを付加することによって単項演算子として解釈させることができます：
sub user_func($);      # 実装にもプロトタイプが必要
user_func 'foo', 'bar', 'baz';
スカラー・コンテキストはさらに
に細分され、評価されます。
長さに制限のない文字列として扱われます。
数値はそのまま文字列に変換され、未定義値は空文字列になります。リファレンスも文字列になりますが、文字列として処理されたリファレンスを再びリファレンスに戻すことはできません：
my ($var, $refvar, $refstr);
$var = 'foo';
$refvar = \$var; #$$refvar eq 'foo'
$refstr = "$refvar";     # 文字列として格納
$$refstr; #エラー; $refstrはもはやリファレンスではない
数値リテラルとして解釈できる文字列は数値として扱われます。それ以外の文字があるとそこで解釈が終了します。
[https://paiza.io/projects/qrQ43FcSOdswPr0C7otw1A?language=perl 例]:
use v5.12;
use warnings;
say sprintf __LINE__ . ": %d", 0 + '12345';
say sprintf __LINE__ . ": %d", 0 + '12345abcde';
say sprintf __LINE__ . ": %d", 0 + '123.45e2';
say sprintf __LINE__ . ": %d", 0 + '0b11000000111001';
say sprintf __LINE__ . ": %d", 0 + '012345';
say sprintf __LINE__ . ": %#x", 0 + '0x12345';
say sprintf __LINE__ . ": %#o", oct '12345';
say sprintf __LINE__ . ": %#x", hex '12345';
実行時エラー:
Argument "12345abcde" isn't numeric in addition (+) at Main.pl line 6.
Argument "0b11000000111001" isn't numeric in addition (+) at Main.pl line 8.
Argument "0x12345" isn't numeric in addition (+) at Main.pl line 10.
実行結果:
5: 12345
6: 12345
7: 12345
8: 0
9: 12345
10: 0x12345
11: 012345 
12: 0x12345
先頭に'0'があっても8進数とは解釈されませんが’0x’が先頭にあると16進数として評価されます。
基数を明示して変換するには oct() 関数や hex() 関数を利用します。
ifやwhileなどの制御構文や修飾文、andやorなどの論理演算子が提供するコンテキストです。
偽となるものは：
であり、残りは全て真と解釈されます。
「文字列'0'」とは'0'という文字列のことであり、数値コンテキストで0と解釈される文字列全てのことではないので注意してください。
次のものは全て真となります：
 '0.0';
 'aaa';
 '0 but true';
評価した結果が捨てられてしまうので、値を期待しないコンテキストです。戻り値のない関数呼び出しなど、副作用を目的として使われます。
副作用もないコードは、perlに-wスイッチをつけて実行すると警告が発せられます：
 'literal';
Perlでは異なるデータ型に対して同じ識別子を与えることができます:
 $foo = 'bar';
 @foo = ( 'bar', 'baz' );
 %foo = ( bar => 'baz' );
 sub foo { return 'bar' };
Perl処理系は内部に識別子テーブルと呼ばれるハッシュを持っています。そのキーは識別子であり、対応する値は''型グロブ''というデータ構造です。型グロブは同じ識別子を持つすべてのデータ型へのリファレンスを格納しています。つまり上記の例だと識別子'foo'の型グロブにはスカラー、配列、ハッシュ、サブルーチンという4つのデータ型へのリファレンスが格納されています。型グロブは識別子の前に'*'というプレフィックスを付加して表現されます:
 *foo;
型グロブ自身はリファレンスを格納したハッシュであり、キーはデータ型の名前です:
 *foo{SCALAR}; # \$foo
 *foo{ARRAY};  # \@foo
 *foo{HASH];   # \%foo
 *foo{CODE};   # \&foo
 *foo{GLOB};   # \*foo; 自分自身へのリファレンス
 *foo{IO};     # ファイルハンドル
 *foo{FORMAT}  # フォーマット
型グロブもデータ構造の一つですから、代入や評価ができます。型グロブに別の型グロブを代入すると、変数の別名（エイリアス）を定義することが出来ます:
 $foo = 'FOO';
 @foo = ( 'FOO', 'BAR' );
 *bar = *foo;
 
 $bar = 'BAR';
 push( @bar, 'BAZ' );
 
 print $foo, "\n";     #BAR
 print @foo, "\n";     #FOOBARBAZ
これはかつてPerlにリファレンスがなかった頃、サブルーチンに引数を参照渡しするのに利用されていました。また、ファイルハンドルとフォーマットにはプレフィックスが存在しないので、これらを受け渡しする場合の唯一の手段でもありました。
 for ( $i = 0; getline( *line ) != -1; $i++ ) {
     print "line $i: $line";
 }
 
 sub getline {
     local (*l) = @_;
     return defined( $l =  ) ? length( $l ) : -1;
 }
現在ではリファレンスが利用できるので、型グロブを使う必要はありません。ファイルハンドルやフォーマットに関してもIOモジュールなどでオブジェクトとして扱うことができます。
なお、型グロブは識別子テーブルの実体そのものですから、ブロックに結び付けられたレキシカルスコープにすることはできません。言い換えると、local変数にはできるがmy変数にはできません。
また、特定のデータ型のリファレンスを代入すると、そのデータ型に限定して別名を定義できます:
 $foo = 'FOO';
 @foo = ( 'FOO', 'BAR' );
 *bar = \@foo; #配列のみ別名を定義
 
 $bar = 'BAR';
 push( @bar, 'BAZ' );
 
 print $foo, "\n";       #FOO
 print @foo, "\n";       #FOOBARBAZ
 *qux = \&Foo::Bar::baz; # Foo::Barモジュールのbaz関数をqux関数としてインポートする