文字列はダブルクォーテーション(")またはシングルクォーテーション(')で囲んで表現します。
文字列を "..." で囲ったときは、内部の変数が展開されます。また、\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 演算子は文字列の場合に用います。
$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 ではドット(.)演算子を用います。
$str1 = "ABC"; $str2 = "DEF"; $str3 = $str1 . $str2; print "$str3\n";
結果は次のようになります。
ABCDEF
ダブルクォーテーションの中に変数を用いることで連結する方法もあります。
$str3 = "$str1$str2";
文字列の長さ(バイト数)を求めるには length() を用います。日本語は、文字コードによって長さが異なるので注意してください。シフトJISの場合は通常、半角カタカナが1バイト、全角文字が2バイトと数えられます。(→ 日本語混じり文の文字数を数える)
$str = "This is 日本."; $len = length($str); print "len = $len\n";
結果は次のようになります。
len = 13
chop() は、常に最後の 1文字を取り除きます。chop() の引数を省略すると、省略時変数 $_ を対象とします。chop() は、行末の文字が改行コードでなくても削除してしまうので注意してください。また、UNIX 上で Windows 形式のファイルを読みこむ場合は、\r\n の \n のみしか削除しません。
open(IN, "data.txt"); while ($line = <IN>) { chop($line); print "[ $line ]\n"; } close(IN);
chomp() は、Perl 5 で追加された機能です。レコード区切り文字 $/ にマッチする文字を取り除きます。引数を省略すると、省略時変数 $_ を対象とします。UNIX 上で Windows 形式のファイルを扱う場合は、chop() と同様うまく取り除けません。
open(IN, "data.txt"); while ($line = <IN>) { chomp($line); print "[ $line ]\n"; } close(IN);
UNIX システム上に転送された Windows 形式のファイルを読みこむ場合など、OS の差異を気にせずに改行コードを取り去るには、正規表現置換を用いる方法があります。
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/.../ や、'...' と同じ意味を持つ q/.../ などの クォート演算子 を用いることにより、バックスラッシュ(\)によるエスケープの嵐を回避することができます。例えば、
print "<img src=\"dog.gif\" alt=\"dog\">\n";
の代わりに、次のように記述することができます。
print qq/<img src="dog.gif" alt="dog">\n/;
では、ダブルクォート(")やスラッシュ(/)両方を多く含む文字列を書き出す場合はどうすればよいでしょうか。クォート演算子では、スラッシュ(/)の代わりに、任意の記号や括弧を用いることができます。文字列の中に現れそうに無い記号や括弧文字を適当に選んで使用してください。
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(reg, str, n) は、正規表現 reg にマッチする文字を区切り文字として文字列 str を分解し、その配列を返します。n には配列の最大値を指定しますが、省略可能です。str も省略すると省略時変数 $_ を分解します。
$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文字以上のスペース系文字でフィールドを区切ることができます。
$str = "Yamada 26 Tokyo"; @cols = split(/\s+/, $str); foreach $col (@cols) { print "$col\n"; }
結果は以下のようになります。
Yamada 26 Tokyo
substr(str, from, len) は、str の from 番目(最初の文字を 0 とする)から len 文字分の文字列を参照します。len を省略した場合は、文字列の最後までを参照します。
$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() は、代入式の右辺に使用することもできます。例えば、下記のように、str の 3 番目から 3 文字分を別の文字に置き換えることもできます。
$str = "0123456789"; substr($str, 3, 3) = "xxx"; # 0から数えて3文字目から3文字を置き換える print "$str\n";
結果は次のようになります。
012xxx6789
文字列の一部を置き換えるには、他にも s/.../.../ による置換の方法もあります。
substr() を用いて、文字を1文字ずつ取り出しながら処理します。日本語混じりの文字列はうまく処理できないので注意してください。(→ 日本語混じり文を1文字ずつ処理する)
$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(str1, str2) は、文字列 str1 の中から文字列 str2 を捜し、最初に現れる位置(最初の文字を 0 番目とする)を返します。rindex() は最初に現れる位置ではなく、最後に現れる位置を返します。
$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 の内容が変更されることはありません。
$str = "Sasagawa Masataka"; $count = ($str =~ tr/a//); print "count = $count\n";
実行結果は次のようになります。
count = 8
a の部分を abc にすると、a または b または c の文字数をカウントします。
ヒアドキュメント を用いて、複数行にわたる文字列を変数に代入することができます。
$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() は、printf() の書式に従って文字列を整形したものを返します。整形により、数値を0埋めしたり、文字の表示幅を揃えたりすることができます。下記の例では、$year を 0埋め4桁で、$mon と $mday を 0埋め2桁の数値で表現します。
$year = 1992; $mon = 4; $mday = 1; $time = sprintf("%04d/%02d/%02d", $year, $mon, $mday); print "$time\n";
実行結果は次のようになります。
1992/04/01
%04d や %02d の説明については printf のフォーマット一覧 を参照してください。
ちょっとマニアックなテクニックを紹介します。文字列中にサブルーチンの戻り値を埋めこむテクニックです。
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 の文章を実行するには次のようにします。これにより、PHP のようなスタイルで CGI を記述することができるようになります。
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 の値が参照されます。
"A" は 65、"B" は 66、"C" は 67 のように、コンピュータ内部では文字を 文字コード として扱っています。文字から文字コードへの変換には ord() や unpack() を用います。
$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() を用います。
$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/.../.../ を用いて小文字を大文字に変換することができます。
$str = "This is Japan."; $str =~ tr/[a-z]/[A-Z]/; print "$str\n"; # "THIS IS JAPAN." となる
\U...\E は、\U と \E で囲まれた部分を大文字に変換します。小文字に変換するには \L...\E を用います。
print "\UThis is Japan.\E\n"; # "THIS IS JAPAN." となる print "\LThis is Japan.\E\n"; # "this is japan." となる
Perl 5 からは、全ての文字を大文字に変換する uc()、最初の1文字を大文字に変換する ucfirst()、すべての文字を小文字に変換する lc()、最初の1文字を小文字に変換する lcfirst() がサポートされました。
print uc("this is Japan.\n"); # "THIS IS JAPAN." となる print ucfirst("this is Japan.\n"); # "This is Japan." となる
いずれの場合も、JISコードやシフトJISコードの日本語を含む文字の場合は、文字化けが発生する可能性があります。一度、EUC に変換して大文字化(小文字化)することでこの問題を解決できます。