Search A.I.
Menu
ホーム

メールマガジン ホームページプログラミングテク

Windowsテク
Javaアプレット サンプル
Java Q & A
JavaScript Q & A
Perl Q & A
Perl レッスン
PHP レッスン
PHPテク
MS-DOS コマンド集
UNIX コマンド集
SQL コマンド集
SEの基礎講座
WEBシステム開発受注します
]無料フォームメール送信サービス
リンク集
Perl レッスン

1. Perl の基礎
2. Perlの文法、条件式
3. Perlの文法、条件式 - 続き
4. 配列について
5. ハッシュ配列について
6. Perlの基礎 - 続き
7. 関数について
8. 関数について - 続き
9. 文字列操作関数
10. 配列操作関数
11. ファイル操作
12. ファイル操作 - 続き
13. パラメータの受け渡し
14. クッキーについて
15. 総合練習
16. メール送信
17. ファイルアップロード
18. パッケージの使用方法
19. MySQL
20. MySQL - 続き(1)
21. MySQL - 続き(2)
22. PostgreSQL
23. 総合練習
24. 総合練習解答



9. 文字列操作関数

今日は、文字列操作関数について、ご説明いたします。

■文字列操作の関数
以前、文字列の結合や判定方法をご紹介しましたが、それに加え、文字列を自在に
操作するPerl関数を一気にご紹介します。

lc($str) アルファベットの大文字を小文字に変換します。
uc($str) アルファベットの小文字を大文字に変換します。
length($str) 文字列$strのバイト数を返します。
substr($str, $num1, $num2)
文字列$strの$num1番目から、$num2の長さ分切り出します。
index($str1, $str2)
文字列$str1の中から最初の$str2を検索し、位置を返します。
rindex($str1, $str2)
文字列$str1の中から最後の$str2を検索し、位置を返します。
sprintf($format, $str1, $str2, $str3, ・・・)
指定した書式にフォーマットします。

文字列操作関数は他にもありますが、よく使用されるのは、上記のものが多いです。

以下にサンプルを記述します。

-----------------------------------------------------------------
$a = "ABc";

# 文字列を小文字に変換
$a = lc($a);
print $a;

# 文字列を大文字に変換
$a = uc($a);
print $a;

# 文字列のサイズを取得
print length($a);

# 文字列の切り出し
$str1 = "This is a test.";
$str2 = substr($str1, 10, 4);
print $str2;

# 文字列の検索
print index($str1, "is");
print rindex($str1, "is");

# 文字列をフォーマット
($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
$year += 1900;
$mon++;

$str3 = sprintf("%4d/%02d/%02d %02d:%02d:%02d", $year, $mon, $mday, $hour, $min, $sec);
print $str3;
-----------------------------------------------------------------

アルファベットを小文字にするlc()は、Lower Changeの略だと思えば
覚えやすいと思います。

また、uc()は、Upper Changeの略だと思います。

length()ですが、バイト数が返ってくるので、文字数とは違います。
日本語などの全角の文字は 1 文字 2 バイトです。
例えば、

$a = "テスト";
print length($a);

の場合は、6 が返ってきます。

substr()は、最初の文字から切り出す場合、0 から始まることに注意してください。
3 つ目の引数は、切り出す長さを指定します。

index()は、文字列検索です。上のサンプル場合、"is"を先頭から検索し、位置を
返します。この位置も、0 番目から数えた値になります。

rindex()は、文字列を逆から検索します。上のサンプルでは、"is"が 2 箇所ある
ので、後ろにある"is"の位置が返ってきます。また、この場合の戻り値も、先頭の
0 番目から数えた値になります。

次に、sprintf()ですが、まず、1 番目の引数に、出力したいフォーマットの
文字列を渡します。

ここで、%4dや、%02dなどがありますが、こちらを簡単にご説明します。

%dと記述すると、数字を文字列にしていると考えてください。例えば、

sprintf("%d", 4);

とするだけで、文字列の"4"が返ります。

%2dと記述すると、整数の 2 桁を文字列に変換することになります。例えば、

sprintf("%2d", 4);

とすると、" 4"が返ります。桁数が多くても、切り捨てられることはないようです。

%02dと記述すると、桁数が少ない場合に、前に 0 を付けます。例えば、

sprintf("%02d", 4);

とすると、"04"が返ります。

また、一気に文字列フォーマットを作成する場合は、

sprintf("%04d/%02d/%02d", $year, $mon, $mday);

のように記述すれば、第2引数以降、順番に出力されます。

他にも書式はありますが、とりあえずこのくらいを覚えておけば十分です。

■パターンマッチ
ある特定の文字を検索したい場合に、特殊な書き方で文字列を検索する方法が
あります。

m/検索文字列/

のような記述になります。"/"以外でくくる記述方法もありますが、混乱を
防ぐため、ここでは紹介しません。また、先頭の"m"は省略可能です。

実際には、

-----------------------------------------------------------------
$a = "http://www.google.co.jp/";
if ($a =~ m/http:\/\/www\./) {
print "Matched.";
}
-----------------------------------------------------------------

のように使用します。比較を行う場合は、必ず =~ を使用します。

上のサンプルは、"http://www."という文字列にマッチしているかを検索して
います。

"/"の前の"\"はエスケープシーケンスになります。("/"は特殊文字のため)
また、"."も特殊文字になりますので、文字として扱う場合は、"\"が必要です。

また、このパターンマッチには、オプションを使用することができます。
代表的なものとして、

m/・・・/i # アルファベットの大文字小文字を区別しない

のように、最後にオプションの文字を付けます。

以下に別のサンプルを記述します。

-----------------------------------------------------------------
$a = "29307";
if ($a =~ m/[0-9]/) {
print "All number.";
}

$a = "This is a test.";
if ($a =~ m/this.*test/i) {
print "Matched.";
}

$a = "39abc";
if ($a !~ /^[a-zA-Z]/) {
print "Miss matched.";
}
-----------------------------------------------------------------

一番上は、数字のチェックを行っています。サンプルのように、"-"を使用すると、
どの文字からどの文字までを検索するという意味になります。この場合、[ ] で
くくります。

次のサンプルの".*"は、間に任意の文字が入るという意味になります。サンプルの
場合、大文字小文字の区別なしで、「this・・・testに一致する」という判定に
なります。

最後は、文字が一致しない場合の検索になります。 !~ と ^ を使用する点に
注意してください。サンプルの場合、「アルファベット以外の文字が含まれる」
という判定になります。

■文字列の置換
次に、文字列の置換方法についてご紹介します。

s/検索文字列/置換文字列/

のようにします。実際には、

-----------------------------------------------------------------
$a = "This is a test.";
$a =~ s/test/sample/;
print $a; # This is a sample.
-----------------------------------------------------------------

のように使用します。パターンマッチの時と同じく、 =~ を使用することと、
別の変数に代入することはできないことに注意してください。

また、パターンにマッチしない場合は、$aはそのままになります。

オプションとして、

s/・・・/・・・/g # 一致したもの全てを置換
s/・・・/・・・/i # アルファベットの大文字小文字を区別しない

などがあります。

-----------------------------------------------------------------
$a = "This is a test.";
$a =~ s/this.*a/That was a/i;
print $a; # That was a test.

$a = "This is a test.";
$a =~ s/is/at/g;
print $a; # That at a test.

$a = "This ia a test.";
$a =~ s/t/w/gi;
print $a; # whis is a wesw.

$a = "This is a test.";
$a =~ s/t|a/w/g;
print $a; # whis is w wesw.

$a = "This is a test.";
$a =~ s/ //g;
print $a; # Thisisatest.

$a = "0120-111-222";
$a =~ s/(\d{4})\-(\d{3})\-(\d{3})/$1\($2\)$3/g;
print $a; # 0120(111)2222
-----------------------------------------------------------------

一番上のサンプルは、大文字小文字の区別なしで、「this・・・aをThat was aに
置換する」という意味になります。

次は、"is"を"at"に置換していますが、オプションの g を付けているため、
全ての"is"が"at"に置換されています。

オプションを複数付けることも可能です。3 番目のサンプルは、大文字小文字の
区別なしで、すべての"t"を"w"に置換しています。

複数の文字を検索する場合は、"|"を使用すると、4 番目のサンプルのように、
「tまたはaをwに置換する」とすることができます。

5 番目のサンプルは、半角の空白をすべて削除しています。

最後のサンプルは少し難しいですが、まず、(\d)は半角数字を表しており、[0-9]と
同じ意味になります。(\d{4})は、4 桁の半角数字という意味になります。
(\d{2,4})とすると、2 桁以上 4 桁以下の半角数字となります。桁数を指定しない
場合は、(\d+)とします。また、"-"や"()"も特殊文字のため、"\"を付けます。
$1、$2、$3は、参照変数と呼ばれるもので、文字が一致した順番に代入されます。

■文字列変換
文字列の置換であれば、先ほどのs/.../.../で十分ですが、さらに特殊な文字列
変換をご紹介します。

tr/文字集合/変換文字集合/

この場合、文字集合の中から、1文字ずつ、変換文字集合に変換されていきます。

例えば、

-----------------------------------------------------------------
$a = "abcdef";
$a =~ tr/ed/xyz/;
print $a; # abcyxf
-----------------------------------------------------------------

の場合、出力は"abcyxf"となります。つまり、"e"を"x"に、"d"を"y"にと、
変換することになります。"z"は該当する検索文字がないため、無視されます。

また、

-----------------------------------------------------------------
$a = "abcdef";
$a =~ tr/abc/xy/;
print $a; # xyydef
-----------------------------------------------------------------

の場合、出力は"xyydef"になります。最後の"c"に該当する文字がないため、
最後の"y"が繰り返し変換されます。

オプションは、

tr/・・・/・・・/c # 文字集合の補集合を変換
tr/・・・/・・・/s # 変換後に同じ文字が重なったときに一文字に縮める

などがあります。

-----------------------------------------------------------------
$a = "abcdef";
$a =~ tr/cbf/z/c;
print $a; # zbczzf

$a = "abcdef";
$a =~ tr/cbf/z/s;
print $a; # azdez
-----------------------------------------------------------------

最初のサンプルは、オプションの"c"で補集合の方を変換します。補集合という
のは、文字集合に含まれない文字のことになります。サンプルの場合、"cbf"の
文字以外の"ade"がそれぞれ"z"に変換されます。

次のサンプルは、オプションの"s"で、変換後に文字が重なっている場合に
一文字に縮めています。サンプルの場合、"azzdez"となるところを"z"が重なって
いるので、縮められて"azdez"になります。

 

★今日のまとめサンプルプログラム
-----------------------------------------------------------------
#! /usr/local/bin/perl

print "Content-type:text/html\n\n";

print << "END_OF_HTML";
<HTML>
<BODY>
END_OF_HTML

$mail = 'TEST@homepage.co.jp';

# 小文字に変換
$mail = lc($mail);
print $mail . "<br>";

# 文字列のバイト数を表示
print "文字の長さは" . length($mail) . "バイトです。<br>";

# "@"の前の文字を取得
print "アカウントは" . substr($mail, 0, index($mail, '@')) . "<br>";

# "@"と"."が含まれているかの判定
if ($mail =~ m/@.*\./) {
print "メールアドレスの形式です。<br>";
}

# .co.jpを.comに置換
$mail =~ s/\.co\.jp/\.com/g;
print $mail . "<br>";

print << "END_OF_HTML";
</BODY>
</HTML>

END_OF_HTML

exit;
-----------------------------------------------------------------

■解説
substr()関数の第3引数は、切り抜きする長さですから、0 番目から
index($mail, '@')で、"@"までを切り抜くことができます。

m/.../を使用すると、簡易的なメールチェックを行えます。サンプルでは、
「$mailに @〜. という文字が含まれている」という判定になります。
"."は特殊文字ですので、エスケープシーケンス"\"を付けます。

文字列を置換する場合は、s/.../.../を使用します。この場合、オプションの
"g"はなくても問題ありません。

 

★課題
1. 以下の処理を行うプログラムを作成してください。

(1) 'test@homepage.co.jp'の文字列から、"@"と最初の"."の間の文字列を出力する
(2) 現在日時を取得し、'2004年01月01日 00時00分00秒'の形式で出力する
(3) 'abc123'という文字列が、半角英数字のみかどうかを判定する
(4) 'test'、'TEST'、'Test'のどの文字がきても、'Test'に置換して出力する
(5) '100円'、'98765円'のような文字を、'\100'、'\98765'に置換して出力する

 

★前回の課題の解答
1. 次の関数を作成し、別ファイルにまとめてパッケージ化してください。

(1) 2つの引数を受け取り、それぞれ 2で割った値を返す関数
(2) 3つの引数を受け取り、"・・・番目の引数は・・・"という文字列をそれぞれに
付け足して返す関数
(3) 現在日時を、"2005/1/1 12:00:00"というフォーマットで返す関数
(4) 現在の曜日を
('日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日')
のいずれかで返す関数
(5) 0 〜 9秒間、ランダムでプログラムが停止(スリープ)する関数

→下のサンプルを参照してください。

test.pl
-----------------------------------------------------------------
package Test;

# (1) 2つの引数を受け取り、それぞれ 2で割った値を返す関数
sub sub_1 {
$_[0] /= 2;
$_[1] /= 2;
}

# (2) 3つの引数を受け取り、"・・・番目の引数は・・・"という文字列をそれぞれに
# 付け足して返す関数
sub sub_2 {
$_[0] = "1番目の引数は" . $_[0];
$_[1] = "2番目の引数は" . $_[1];
$_[2] = "3番目の引数は" . $_[2];
}

# (3) 現在日時を、"2005/1/1 12:00:00"というフォーマットで返す関数
sub sub_3 {
($sec,$min,$hour,$mday,$mon,$year) = localtime(time);

$year += 1900;
$mon++;

return "$year/$mon/$mday $hour:$min:$sec";
}

# (4) 現在の曜日を返す関数
sub sub_4 {
($sec,$min,$hour,$mday,$mon,$year,$wday) = localtime(time);
@week = ('日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日');

return $week[$wday];
}

# (5) 0 〜 9秒間、ランダムでプログラムが停止(スリープ)する関数
sub sub_5 {
sleep(int(rand(9)));
}

1;
-----------------------------------------------------------------

index.cgi
-----------------------------------------------------------------
#! /usr/local/bin/perl

require './test.pl';

print "Content-type:text/html\n\n";

print << "END_OF_HTML";
<HTML>
<BODY>
END_OF_HTML

# (1)
$a = 56;
$b = 82;

Test::sub_1($a, $b);

print $a . "<br>" . $b;
print "<br>";

# (2)
$a = "TEST1";
$b = "TEST2";
$c = "TEST3";

Test::sub_2($a, $b, $c);
print $a . "<br>" . $b . "<br>" . $c;
print "<br>";

# (3)
print Test::sub_3();
print "<br>";

# (4)
print Test::sub_4();
print "<br>";

# (5)
Test::sub_5();

print << "END_OF_HTML";
</BODY>
</HTML>

END_OF_HTML

exit;
-----------------------------------------------------------------

■解説
$_[0] /= 2 は、 $_[0] = $_[0] / 2 と同じ意味ですね。引数に直接代入する
ことで、呼び出し側にも反映されます。

localtime()の戻り値は、受け取りに必要なければ、後ろから順に省略することが
できます。

sleepの引数は、整数ですので、int()を使用して、rand()関数の戻り値を整数に
変換する必要があります。




前の章へ 次の章へ


このエントリーをはてなブックマークに追加


OfficeLance

お問い合わせはこちらから