文字列

■ 文字列を用いる

◆ 文字列

文字列はダブルクォーテーション(")またはシングルクォーテーション(')で囲んで表現します。

◆ ダブルクォーテーションによる文字列

文字列を "..." で囲ったときは、内部の変数が展開されます。また、\n などの エスケープシーケンス を用いることができます。

$num = 5;
print "答えは $num です。\n";

実行すると次のようになります。

答えは 5 です。
◆ シングルクォーテーションによる文字列

文字列を '...' で囲ったときは、変数の展開は行われません。また、エスケープシーケンス も解釈されません。

$num = 5;
print '答えは $num です。\n';

実行すると次のようになります。

答えは $num です。\n
◆ クォーテーションの無い文字列

実は Perl では、それが文字列であることが明白であれば、クォーテーションを書かなくてもよいという規則があります。例えば、次の例では Hello は文字列として扱われます。

$str = Hello;
print "str = $str\n";

ただし、Hello がサブルーチンとして定義されている場合は、サブルーチンの結果が代入されます。混乱を避けるためにもクォーテーションは記述しましょう。

sub Hello { return "Bye!!\n"; }
$str = Hello;
print "str = $str\n";

■ 文字列の中で変数を使用する

◆ 文字列中の変数展開

"..." のに直接変数を記述すると、変数の値が展開されて表示されます。

$len = "31.5";
print "長さは $lenセンチメートルです。\n";

結果は次のようになります。

長さは 31.5センチメートルです。

変数名と文字列の区切りが不明確な場合は、変数名を {...} で囲むことによって、変数名を明確にすることができます。

$len = "31.5";
print "長さは ${len}cmです。\n";

■ 改行する

◆ 改行コード

改行するには、"..." の文字列の中で \n を指定します。\n のように、円マーク(\)を用いた特殊文字を エスケープシーケンス と呼びます。改行(\n)の他にも、復帰(\r)、タブ(\t)などがあります。詳細は エスケープシーケンス一覧 を参照してください。

print "あけまして\nおめでとう\nございます。\n";

結果は次のようになります。

あけまして
おめでとう
ございます。

■ 文字列を比較する

◆ 文字列の比較

文字列を比較するには == 演算子ではなく、eq 演算子を用います。== や < や > 演算子は数値の場合に、eq や gt や lt 演算子は文字列の場合に用います。

strcmp.pl
$str1 = "Hello";
$str2 = "Hello";

if ($str1 eq $str2) {
    print "同じです。\n";
} else {
    print "異なります。\n";
}

実行結果は次のようになります。

同じです。
◆ 文字列比較演算子のいろいろ

文字列演算子と、数値演算子の対応表を示します。

数値演算子文字列演算子説明
==eq等しい。(equal)
!=ne等しくない。(not equal)
<lt小さい。(less than)
>gt大きい。(greater than)
<=le小さいか等しい。(less than or equal)
>=ge大きいか等しい。(greater than or equal)
<=>cmp比較結果を -1, 0, 1 で返す。(compare)

文字演算で「小さい」や「大きい」は、文字コードによって決まります。例えば "B" は "A" よりも大きく、"C" よりも小さな文字です。

■ 文字列を連結する

◆ 文字列の連結

JavaScript などでは文字列を連結するのに + 演算子を用いますが、Perl ではドット(.)演算子を用います。

strcat.pl
$str1 = "ABC";
$str2 = "DEF";
$str3 = $str1 . $str2;
print "$str3\n";

結果は次のようになります。

ABCDEF

ダブルクォーテーションの中に変数を用いることで連結する方法もあります。

$str3 = "$str1$str2";

■ 文字列の長さを求める(length)

◆ 文字列の長さ

文字列の長さ(バイト数)を求めるには length() を用います。日本語は、文字コードによって長さが異なるので注意してください。シフトJISの場合は通常、半角カタカナが1バイト、全角文字が2バイトと数えられます。(→ 日本語混じり文の文字数を数える

length.pl
$str = "This is 日本.";
$len = length($str);
print "len = $len\n";

結果は次のようになります。

len = 13

■ 改行コードを取り除く(chop, chomp)

◆ chop() による改行削除

chop() は、常に最後の 1文字を取り除きます。chop() の引数を省略すると、省略時変数 $_ を対象とします。chop() は、行末の文字が改行コードでなくても削除してしまうので注意してください。また、UNIX 上で Windows 形式のファイルを読みこむ場合は、\r\n の \n のみしか削除しません。

chop.pl
open(IN, "data.txt");
while ($line = <IN>) {
    chop($line);
    print "[ $line ]\n";
}
close(IN);
◆ chomp() による改行削除

chomp() は、Perl 5 で追加された機能です。レコード区切り文字 $/ にマッチする文字を取り除きます。引数を省略すると、省略時変数 $_ を対象とします。UNIX 上で Windows 形式のファイルを扱う場合は、chop() と同様うまく取り除けません。

chomp.pl
open(IN, "data.txt");
while ($line = <IN>) {
    chomp($line);
    print "[ $line ]\n";
}
close(IN);
◆ 正規表現による改行削除(オススメの方法)

UNIX システム上に転送された Windows 形式のファイルを読みこむ場合など、OS の差異を気にせずに改行コードを取り去るには、正規表現置換を用いる方法があります。

delbreak.pl
open(IN, "data.txt");
while ($line = <IN>) {
    $line =~ s/[\r\n]*$//;
    print "[ $line ]\n";
}
close(IN);

■ クォーテーションを含む文字列を書き出す

◆ ダブルクォーテーション文字列("...")の場合

"..." の中には、シングルクォーテーション(')をそのまま記述することができます。

print "<body bgcolor='red'>\n";

ダブルクォーテーション(")を記述する時は、" を \" と記述します。これを、バックスラッシュ(\)で " を エスケープ するといいます。エスケープすることで、" が持つ特別な意味を無効化します。

print "<body bgcolor=\"red\">\n";

上記の 2行を実行すると下記のように表示されます。

<body bgcolor='red'>
<body bgcolor="red">
◆ シングルクォーテーション文字列('...')の場合

'...' の中には、ダブルクォーテーション(")をそのまま記述することができます。

print '<body bgcolor="red">' . "\n";

シングルクォーテーション(')を記述する時は、' を \' と記述します。ただし、\n などはエスケープシーケンスとしては認識されません。

print '<body bgcolor=\'red\'>' . "\n";

上記の 2行を実行すると下記のように表示されます。

<body bgcolor="red">
<body bgcolor='red'>

■ クォーテーションを多量に含む文字列を書き出す(qq/.../)

◆ クォート演算子

"..." と同じ意味を持つ qq/.../ や、'...' と同じ意味を持つ q/.../ などの クォート演算子 を用いることにより、バックスラッシュ(\)によるエスケープの嵐を回避することができます。例えば、

print "<img src=\"dog.gif\" alt=\"dog\">\n";

の代わりに、次のように記述することができます。

print qq/<img src="dog.gif" alt="dog">\n/;
◆ " や / を多く含む文字列の書き出し

では、ダブルクォート(")やスラッシュ(/)両方を多く含む文字列を書き出す場合はどうすればよいでしょうか。クォート演算子では、スラッシュ(/)の代わりに、任意の記号や括弧を用いることができます。文字列の中に現れそうに無い記号や括弧文字を適当に選んで使用してください。

quote.pl
print qq/<img src="\/image\/dog.gif" alt="dog">\n/;
print qq|<img src="/image/cat.gif" alt="cat">\n|;
print qq(<img src="/image/fox.gif" alt="fox">\n);

これを実行すると、次のようになります。

<img src="/image/dog.gif" alt="dog">
<img src="/image/cat.gif" alt="cat">
<img src="/image/fox.gif" alt="fox">

■ 文字列をカンマで区切る(split)

◆ 文字列をカンマで区切る

split(reg, str, n) は、正規表現 reg にマッチする文字を区切り文字として文字列 str を分解し、その配列を返します。n には配列の最大値を指定しますが、省略可能です。str も省略すると省略時変数 $_ を分解します。

split1.pl
$str = "AAA,BBB,CCC";
@cols = split(/,/, $str);
foreach $col (@cols) {
    print "$col\n";
}

上記を実行すると、"AAA,BBB,CCC" がカンマ(,)で区切られて、以下のように出力されます。

AAA
BBB
CCC

■ 文字列をホワイトスペースで区切る

◆ 文字列をホワイトスペースで区切る

ホワイトスペース とは、1文字以上の空白、タブ(\t)、改行(\n)、復帰(\r)、フォームフィード(\f)を意味します。split() の第一引数を /\s+/ とすることで、1文字以上のスペース系文字でフィールドを区切ることができます。

split2.pl
$str = "Yamada  26   Tokyo";
@cols = split(/\s+/, $str);
foreach $col (@cols) {
    print "$col\n";
}

結果は以下のようになります。

Yamada
26
Tokyo

■ 文字列の一部を参照する(substr)

◆ 文字列の一部を参照する

substr(str, from, len) は、strfrom 番目(最初の文字を 0 とする)から len 文字分の文字列を参照します。len を省略した場合は、文字列の最後までを参照します。

substr1.pl
$str = "0123456789";
$xx = substr($str, 3, 3);   # 0から数えて3文字目から3文字
print "$xx\n";
$xx = substr($str, 3);      # 0から数えて3文字目から最後まで
print "$xx\n";

結果は以下のようになります。

345
3456789

■ 文字列の一部を書きかえる(substr)

◆ 文字列の一部を書きかえる

substr() は、代入式の右辺に使用することもできます。例えば、下記のように、str の 3 番目から 3 文字分を別の文字に置き換えることもできます。

substr2.pl
$str = "0123456789";
substr($str, 3, 3) = "xxx";  # 0から数えて3文字目から3文字を置き換える
print "$str\n";

結果は次のようになります。

012xxx6789

文字列の一部を置き換えるには、他にも s/.../.../ による置換の方法もあります。

■ 文字を1文字ずつ処理する

◆ 文字を1文字ずつ処理する

substr() を用いて、文字を1文字ずつ取り出しながら処理します。日本語混じりの文字列はうまく処理できないので注意してください。(→ 日本語混じり文を1文字ずつ処理する

substr3.pl
$str = "This is Japan.";
$len = length($str);
for ($i = 0; $i < $len; $i++) {
    $c = substr($str, $i, 1);
    print "[$c]";
}
print "\n";

結果は次のようになります。

[T][h][i][s][ ][i][s][ ][J][a][p][a][n][.] 

同様のことを、正規表現を用いた 連続マッチ を用いて行うこともできます。

$str = "This is Japan.";
while ($str =~ /(.)/g) {
    print "[$1]";
}
print "\n";

■ 特定の文字が含まれているか捜す(index, rindex)

◆ 特定の文字が含まれているか探す

index(str1, str2) は、文字列 str1 の中から文字列 str2 を捜し、最初に現れる位置(最初の文字を 0 番目とする)を返します。rindex() は最初に現れる位置ではなく、最後に現れる位置を返します。

index.pl
$str = "ABCABCABC";
$n = index($str, "ABC");   # 最初に "ABC" が現れる位置を探す
$r = rindex($str, "ABC");  # 最後に "ABC" が現れる位置を探す
print "n = $n, r = $r\n";

実行結果は次のようになります。

n = 0, r = 6

index()、rindex() いずれも、見つからない場合は -1 を返します。

■ 特定の文字が何文字含まれているか求める

◆ 特定の文字が何文字含まれているか求める

tr/// は本来置換を行う目的で実装された機能ですが、下記のように使用することにより、文字列 $str の中に文字 a が何文字含まれているかを調べることができます。$str =~ tr/a// を行っても、$str の内容が変更されることはありません。

trcount.pl
$str = "Sasagawa Masataka";
$count = ($str =~ tr/a//);
print "count = $count\n";

実行結果は次のようになります。

count = 8

a の部分を abc にすると、a または b または c の文字数をカウントします。

■ 複数行にわたる文字列を代入する

◆ ヒアドキュメントによる代入

ヒアドキュメント を用いて、複数行にわたる文字列を変数に代入することができます。

heredoc.pl
$header = <<END_OF_DATA;
Content-type: text/html; charset=Shift_JIS

<html>
<head>
<title>TEST</title>
</head>
<body>
END_OF_DATA

print "$header\n";

END_OF_DATA をシングルクォートで囲むと、変数の展開やエスケープシーケンスが抑制されます。

■ 書式付きの文字列を生成する(sprintf)

◆ 書式付き文字列に整形する

sprintf() は、printf() の書式に従って文字列を整形したものを返します。整形により、数値を0埋めしたり、文字の表示幅を揃えたりすることができます。下記の例では、$year を 0埋め4桁で、$mon と $mday を 0埋め2桁の数値で表現します。

sprintf.pl
$year = 1992;
$mon = 4;
$mday = 1;
$time = sprintf("%04d/%02d/%02d", $year, $mon, $mday);
print "$time\n";

実行結果は次のようになります。

1992/04/01

%04d や %02d の説明については printf のフォーマット一覧 を参照してください。

■ 文字列の中でサブルーチンを展開する

◆ 文字列中のサブルーチンの展開

ちょっとマニアックなテクニックを紹介します。文字列中にサブルーチンの戻り値を埋めこむテクニックです。

subinstr.pl
print <<END_OF_DATA;
<html>
<head>
<title>TEST</title>
</head>
<body>
${body()}
</body>
</html>
END_OF_DATA

sub body {
    $body = "Hello world!!";
    return "body";
}

これを実行すると次のようになります。

<html>
<head>
<title>TEST</title>
</head>
<body>
Hello world!!
</body>
</html>
◆ 説明

スクリプトを実行すると、${body()} を表示しようとした時点でサブルーチン body() が実行されます。戻り値が "body" なので、${body()} は ${"body"} に展開されます。${"body"} は $body と同じ意味なので、body() の中で設定された外部変数 $body が展開されます。

■ 文字列の中でPerl文を実行する

◆ 文字列の中でPerl文を実行する

前ページのテクニックと同様に、文字列の中で Perl の文章を実行するには次のようにします。これにより、PHP のようなスタイルで CGI を記述することができるようになります。

perlinstr.pl
print <<END_OF_DATA;
<html>
<head>
<title>TEST</title>
</head>
<body>
${
    while ($file = <*>) {
        $FILELIST .= "<div>$file</div>\n";
    }
    "FILELIST";
}
</body>
</html>
END_OF_DATA
◆ 説明

${ から } までの間に Perl のスクリプトを書き込みます。結果をひとつの変数に代入して、最後に、その変数名を記述します。全ページの仕組みと同様、${...} が ${FILELIST} に展開され、$FILELIST の値が参照されます。

ひとくちメモ

PHP は Perl/CGI の組み合わせの代わりによく用いられる言語で、HTML の中に <% スクリプト %> のような形式で記述します。構文は Perl によく似ています。HTML 中に記述する点では JavaScript に似ていますが、実行がサーバー側で行われる点は Perl/CGI に似ています。PHP と同様のものに ASPJSP などがあります。

■ 文字から文字コードに変換する

◆ 文字から文字コードへの変換

"A" は 65、"B" は 66、"C" は 67 のように、コンピュータ内部では文字を 文字コード として扱っています。文字から文字コードへの変換には ord()unpack() を用います。

ord.pl
$chr = ord("A");              # 文字から文字コードへの変換(1)
print "A => $chr\n";

@chr = unpack("C*", "ABC");   # 文字から文字コードへの変換(2)
print "ABC => @chr\n";

これを実行すると次のようになります。

A => 65
ABC => 65 66 67

■ 文字コードから文字に変換する

◆ 文字から文字コードへの変換

文字コードから文字への変換には chr()sprintf()pack() を用います。

chr.pl
$str = chr(65);                       # 文字コードから文字への変換(1)
print "65 => $str\n";

$str = sprintf("%c%c%c", 65, 66, 67); # 文字コードから文字への変換(2)
print "65 66 67 => $str\n";

$str = pack("C*", 65, 66, 67);        # 文字コードから文字への変換(3)
print "65 66 67 => $str\n";

これを実行すると次のようになります。

65 => A
65 66 67 => ABC
65 66 67 => ABC

■ 小文字・大文字変換する

◆ tr/.../.../ を用いる方法

tr/.../.../ を用いて小文字を大文字に変換することができます。

uplow.pl(1)
$str = "This is Japan.";
$str =~ tr/[a-z]/[A-Z]/;
print "$str\n";                      # "THIS IS JAPAN." となる
◆ \U...\E、\L...\E を用いる方法

\U...\E は、\U と \E で囲まれた部分を大文字に変換します。小文字に変換するには \L...\E を用います。

uplow.pl(2)
print "\UThis is Japan.\E\n";       # "THIS IS JAPAN." となる
print "\LThis is Japan.\E\n";       # "this is japan." となる
◆ uc(), lc() を用いる方法

Perl 5 からは、全ての文字を大文字に変換する uc()、最初の1文字を大文字に変換する ucfirst()、すべての文字を小文字に変換する lc()、最初の1文字を小文字に変換する lcfirst() がサポートされました。

uplow.pl(3)
print uc("this is Japan.\n");       # "THIS IS JAPAN." となる
print ucfirst("this is Japan.\n");  # "This is Japan." となる
◆ 日本語を用いた場合の注意

いずれの場合も、JISコードやシフトJISコードの日本語を含む文字の場合は、文字化けが発生する可能性があります。一度、EUC に変換して大文字化(小文字化)することでこの問題を解決できます。


Copyright (C) 2002 杜甫々