Perl
#22
TIOBE#13
PYPL#29
GitHub#33
IEEESpectrum#25
プログラミング言語
Perl
概要
Perlは「実用的テキスト抽出・レポート言語」として開発された、強力なテキスト処理機能を持つプログラミング言語です。
詳細
Perlは1987年にLarry Wall氏によって開発されたインタープリター型のプログラミング言語で、「There's more than one way to do it(一つのことを行うのに複数の方法がある)」という哲学で知られています。正規表現のネイティブサポート、豊富な文字列操作機能、連想配列(ハッシュ)の標準搭載など、テキスト処理に特化した設計が特徴です。システム管理、ログ解析、Web開発、バイオインフォマティクスなどの分野で広く利用されており、CPANという巨大なライブラリエコシステムを持っています。モダンPerlでは、オブジェクト指向プログラミングや関数型プログラミングの機能も充実しています。
書き方の例
Hello World
#!/usr/bin/perl
use strict;
use warnings;
# 基本的な出力
print "Hello, World!\n";
# 変数を使った出力
my $message = "こんにちは、Perl!";
print "$message\n";
# フォーマット出力
my $name = "太郎";
my $age = 25;
printf "私の名前は%sで、%d歳です。\n", $name, $age;
# say関数(Perl 5.10以降)
use feature 'say';
say "改行が自動的に追加されます";
変数とデータ型
#!/usr/bin/perl
use strict;
use warnings;
# スカラー変数($記号)
my $number = 42;
my $float = 3.14;
my $string = "文字列";
my $boolean = 1; # Perlには専用のboolean型はない
# 配列(@記号)
my @fruits = ("りんご", "バナナ", "オレンジ");
my @numbers = (1, 2, 3, 4, 5);
my @mixed = ("文字列", 42, 3.14);
# ハッシュ(%記号)
my %person = (
"name" => "田中太郎",
"age" => 30,
"city" => "東京"
);
# 参照(リファレンス)
my $array_ref = \@fruits;
my $hash_ref = \%person;
print "数値: $number\n";
print "配列の要素数: " . scalar(@fruits) . "\n";
print "ハッシュの値: $person{name}\n";
print "参照経由: " . $array_ref->[0] . "\n";
条件分岐
#!/usr/bin/perl
use strict;
use warnings;
# 基本的なif文
my $score = 85;
my $grade;
if ($score >= 90) {
$grade = "A";
} elsif ($score >= 80) {
$grade = "B";
} elsif ($score >= 70) {
$grade = "C";
} else {
$grade = "D";
}
print "得点: $score, 評価: $grade\n";
# unless文(ifの逆)
my $age = 20;
unless ($age < 18) {
print "成人です\n";
}
# 後置if/unless
print "運転できます\n" if $age >= 18;
print "未成年ではありません\n" unless $age < 18;
# given-when文(Perl 5.10以降)
use feature 'switch';
my $day = "水曜日";
given ($day) {
when ("月曜日") { print "週の始まり\n"; }
when ("水曜日") { print "週の中間\n"; }
when ("金曜日") { print "週末まであと少し\n"; }
default { print "他の曜日\n"; }
}
配列とハッシュの操作
#!/usr/bin/perl
use strict;
use warnings;
# 配列の操作
my @fruits = ("りんご", "バナナ", "オレンジ");
# 要素の追加
push @fruits, "ぶどう";
unshift @fruits, "いちご"; # 先頭に追加
# 要素の削除
my $last = pop @fruits; # 末尾から削除
my $first = shift @fruits; # 先頭から削除
print "配列: " . join(", ", @fruits) . "\n";
print "削除した要素: $first, $last\n";
# 配列のスライス
my @selected = @fruits[0, 2]; # インデックス0と2の要素
print "選択した要素: " . join(", ", @selected) . "\n";
# ハッシュの操作
my %person = (
"name" => "田中太郎",
"age" => 30,
"city" => "東京"
);
# 新しいキーと値の追加
$person{"job"} = "エンジニア";
# キーの存在確認
if (exists $person{"age"}) {
print "年齢: $person{age}\n";
}
# すべてのキーと値を取得
my @keys = keys %person;
my @values = values %person;
print "キー: " . join(", ", @keys) . "\n";
# ハッシュのループ
for my $key (keys %person) {
print "$key: $person{$key}\n";
}
ループ処理
#!/usr/bin/perl
use strict;
use warnings;
# for文(C言語スタイル)
for my $i (1..5) {
print "$i の2乗は " . ($i * $i) . "\n";
}
# foreach文
my @numbers = (1, 2, 3, 4, 5);
foreach my $num (@numbers) {
print "数値: $num, 2倍: " . ($num * 2) . "\n";
}
# while文
my $count = 0;
while ($count < 5) {
print "カウント: $count\n";
$count++;
}
# do-while文
my $counter = 0;
do {
print "実行回数: " . ($counter + 1) . "\n";
$counter++;
} while ($counter < 3);
# 後置foreach
print "$_\n" foreach @numbers;
# 範囲演算子
for (1..10) {
print "数値: $_\n"; # $_ はデフォルト変数
}
サブルーチン(関数)
#!/usr/bin/perl
use strict;
use warnings;
# 基本的なサブルーチン
sub greet {
my ($name) = @_;
return "こんにちは、${name}さん!";
}
# デフォルト引数を持つサブルーチン
sub calculate_area {
my ($width, $height) = @_;
$height //= 10; # 定義されていない場合のデフォルト値
return $width * $height;
}
# 複数の値を返すサブルーチン
sub get_name_age {
return ("田中太郎", 25);
}
# 可変長引数
sub sum {
my $total = 0;
$total += $_ foreach @_;
return $total;
}
# サブルーチンの呼び出し
my $message = greet("山田");
print "$message\n";
my $area = calculate_area(5); # heightはデフォルト値を使用
print "面積: $area\n";
my ($name, $age) = get_name_age();
print "名前: $name, 年齢: $age\n";
my $result = sum(1, 2, 3, 4, 5);
print "合計: $result\n";
正規表現とパターンマッチング
#!/usr/bin/perl
use strict;
use warnings;
my $text = "私のメールアドレスは test@example.com です";
# パターンマッチング
if ($text =~ /メール/) {
print "「メール」という文字が見つかりました\n";
}
# 置換
my $new_text = $text;
$new_text =~ s/test/user/; # testをuserに置換
print "置換後: $new_text\n";
# キャプチャグループ
if ($text =~ /(\w+)@(\w+\.\w+)/) {
my $username = $1;
my $domain = $2;
print "ユーザー名: $username, ドメイン: $domain\n";
}
# 複数行テキストの処理
my $multiline = <<'EOF';
行1: これは最初の行です
行2: これは2番目の行です
行3: これは最後の行です
EOF
# 各行を処理
foreach my $line (split /\n/, $multiline) {
if ($line =~ /^行(\d+): (.+)$/) {
print "行番号: $1, 内容: $2\n";
}
}
# グローバルマッチ
my $data = "価格: 100円, 税込: 110円, 送料: 200円";
my @prices = $data =~ /(\d+)円/g;
print "見つかった価格: " . join(", ", @prices) . "\n";
ファイル操作
#!/usr/bin/perl
use strict;
use warnings;
use autodie; # ファイル操作のエラーハンドリングを自動化
# ファイルの書き込み
open my $fh_out, '>', 'sample.txt';
print $fh_out "これはテストファイルです。\n";
print $fh_out "Perlでファイル操作を学んでいます。\n";
close $fh_out;
# ファイルの読み込み
open my $fh_in, '<', 'sample.txt';
while (my $line = <$fh_in>) {
chomp $line; # 改行文字を除去
print "読み込み: $line\n";
}
close $fh_in;
# ファイル全体を一度に読み込み
open my $fh_all, '<', 'sample.txt';
my @lines = <$fh_all>;
close $fh_all;
print "総行数: " . scalar(@lines) . "\n";
# CSV形式のファイル処理
my $csv_data = <<'EOF';
名前,年齢,職業
田中太郎,30,エンジニア
山田花子,25,デザイナー
佐藤次郎,35,マネージャー
EOF
foreach my $line (split /\n/, $csv_data) {
next if $line =~ /^名前/; # ヘッダー行をスキップ
my ($name, $age, $job) = split /,/, $line;
print "名前: $name, 年齢: $age, 職業: $job\n";
}
オブジェクト指向プログラミング
#!/usr/bin/perl
use strict;
use warnings;
# パッケージ(クラス)の定義
package Car;
# コンストラクタ
sub new {
my ($class, $make, $model, $year) = @_;
my $self = {
make => $make,
model => $model,
year => $year,
mileage => 0
};
bless $self, $class;
return $self;
}
# アクセサメソッド
sub make { my $self = shift; return $self->{make}; }
sub model { my $self = shift; return $self->{model}; }
sub year { my $self = shift; return $self->{year}; }
sub mileage { my $self = shift; return $self->{mileage}; }
# インスタンスメソッド
sub drive {
my ($self, $distance) = @_;
$self->{mileage} += $distance;
print "${distance}km 運転しました。総走行距離: $self->{mileage}km\n";
}
sub get_info {
my $self = shift;
return "$self->{year}年式 $self->{make} $self->{model}";
}
# メインパッケージに戻る
package main;
# オブジェクトの作成と使用
my $car = Car->new("トヨタ", "プリウス", 2022);
print $car->get_info() . "\n";
$car->drive(50);
$car->drive(30);
print "現在の走行距離: " . $car->mileage() . "km\n";
特徴的な機能
CPAN(包括的Perlアーカイブネットワーク)
#!/usr/bin/perl
use strict;
use warnings;
# CPANモジュールの使用例
use LWP::Simple; # Webコンテンツの取得
use JSON; # JSON処理
use DateTime; # 日時処理
# Web APIからデータを取得
my $url = "https://api.github.com/users/perl";
my $content = get($url);
if ($content) {
my $data = decode_json($content);
print "ユーザー名: $data->{login}\n";
print "名前: $data->{name}\n";
print "フォロワー数: $data->{followers}\n";
}
# 日時の処理
my $now = DateTime->now();
print "現在時刻: " . $now->strftime('%Y年%m月%d日 %H:%M:%S') . "\n";
特殊変数とコンテキスト
#!/usr/bin/perl
use strict;
use warnings;
# 特殊変数の使用
my @data = ("りんご", "バナナ", "オレンジ");
print "デフォルト変数 \$_:\n";
for (@data) {
print " $_\n"; # $_ は現在の要素
}
# 配列のコンテキスト
my $count = @data; # スカラーコンテキスト(要素数)
my @copy = @data; # 配列コンテキスト(コピー)
print "要素数: $count\n";
print "コピー: " . join(", ", @copy) . "\n";
# 入力行番号
while (my $line = <DATA>) {
chomp $line;
print "行 $.: $line\n"; # $. は現在の行番号
}
__DATA__
データ行1
データ行2
データ行3
ワンライナーとコマンドライン処理
# ファイルの各行に行番号を付ける
perl -pe 'print "$.: "' file.txt
# CSVファイルの特定の列を抽出
perl -F, -ane 'print $F[1], "\n"' data.csv
# 文字列の置換
echo "Hello World" | perl -pe 's/World/Perl/'
# ファイル内の文字列を一括置換
perl -pi -e 's/old/new/g' *.txt
バージョン
バージョン | ステータス | 主要な特徴 | リリース年 |
---|---|---|---|
Perl 5.38 | Latest | 実験的機能の安定化 | 2023 |
Perl 5.36 | Current | builtin機能、signatures改善 | 2022 |
Perl 5.34 | Current | try-catch実験的サポート | 2021 |
Perl 5.32 | Current | チェイン演算子 | 2020 |
Perl 5.30 | Current | 限定的な実験的機能 | 2019 |
Perl 5.28 | 保守版 | Unicode 11.0サポート | 2018 |
参考ページ
公式ドキュメント
- Perl.org - 公式サイト
- Perl Documentation - 公式ドキュメント
- Learn Perl - 公式学習リソース
学習リソース
- Modern Perl - モダンPerlの解説書
- Perl Maven - 実践的なPerlチュートリアル
- PerlMonks - Perlコミュニティフォーラム
開発ツール
- CPAN - 包括的Perlアーカイブネットワーク
- Strawberry Perl - Windows用Perlディストリビューション
- Padre - Perl専用IDE