Perl/CGIプログラムの文字列操作関数(1)
今回から2回にわたって、文字列を操作できる代表的な関数について学習していきます。
文字列を操作できる関数はいくつかありますが、今回はその中でも、split関数について学習していきましょう。
編集前記
今回はちょっとした記念号です。
この Perl/CGI講座 も、やっと10回目を迎えることができました。
え?今回で11回目じゃないかって?
一番初めはCGIとPerlの紹介 なので、あれはカウントしていません。
なので今回は10回目で間違いありません。
というわけで、ここまで続けられたのも、こうしてあなたが読んでくれているおかげです。
ありがとうございます。
こうして書くと、なんだかきれい事のように感じるかもしれませんが、かなり本気です。
なぜなら、これだけの情報を掲載しているのにもかかわらず、アクセス数0とかだったら…
さっさとこのコンテンツに見切りをつけて別のことに力を注いでいるであろうことは容易に想像できますよね。
それに、このPerl/CGI講座を読んでいただければわかると思いますが、ひとつひとつがものすごく長いじゃないですか…。
あまりにも長すぎるので、原稿を書いていても1日では書き終わりません。
もはや、学習の各パートを空き時間に少しずつ書いていき、最後に組み合わせて調整することが当たり前になっています。
まるで、プログラム作成過程のようです。
少しずつ サブルーチン を作っていき、最後にひとつのプログラムを組み上げていくみたいな…。
サブルーチンとの違いは、文章ですから使い回しができないというところでしょうね(苦笑)。
まぁでもいざ書いてみると、これが結構楽しくて、あっという間に時間が過ぎていたりします。
そんな思い入れたっぷりのコンテンツをここまで読んでくれているわけですから、ものすごくうれしいわけですよ。
サイト訪問者のみなさんの立場に立ってみると…。
たかがウェブページ1ページなのに、読んでも読んでもまだ先がある。
まるで、週末の疲れをさらに増加させる勢いですよね(苦笑)。
それなのに、今日までこのコンテンツを参考にして、Perl/CGIプログラミングを学習してくれているわけですから、本当にうれしいです。
ぜひこのまま読み続けて、Perl/CGIプログラミングをマスターしてくださいね。
これからもPerl/CGIプログラミングに役立つ情報を掲載していきます。
さて、今回の編集前記は、10回目を記念して、今後のPerl/CGIプログラミング学習のスタイルについてお話していきます。
冒頭でもお話ししましたが、このPerl/CGI講座の記事は一回一回がものすごく長いです。
長すぎるので…
見ただけでやる気をなくした人
いやいやながらもがんばっている人
この長さが気に入っている人
いろいろいると思います。
そもそもなぜ、このPerl/CGI講座は1回1回が長いんだと思いますか?
いやがらせ?
↑ちがいます(笑)。
なぜかと言うと、「Perl/CGIプログラミング学習には覚えることがたくさんあるから」ですね。
ほかにもいろいろあるんですが、一番大きな理由はこれです。
仮に覚えることが少なければ、このPerl/CGI講座も、もっとスマートになっていたかと思います。
それ以前に覚える量が少なければ、わざわざこのページで解説していく意味ないので、おそらくこのPerl/CGI講座は存在しなかったでしょう。
でも、Perl/CGIプログラミングをする上で学習すべきことはたくさんあります。
そう簡単にはいかないわけですね。
だから、Perl/CGI講座は長くなってしまうというわけです。
次に、たくさんあるPerl/CGIプログラミング学習メディアの中から、あなたがこのサイトを選んでくれたという行為に答えたいという思いがあります。
どういうことかと言うと…。
書店には辞書ぐらいのぶあつい本が並んでいます。
インターネットで検索すれば、たくさんのページがヒットします。
学校や通信教育もたくさんあります。
有料無料問わず今は、本当にいろいろなメディアがあり、学習方法も自由に選べるようになりました。
その中であなたに、このウェブサイトをひとつの学習手段に選んでいただいたわけですから、教える側にもある程度責任があると思っています。
とはいっても、このページは有料ではありませんから、本当ならそんな責任感じる必要ないんです。
無料なんですから、書き手は自由に文章を書き、あなたは学習したい部分のみを自己責任で取捨選択していく。
そんな逃げ道が用意されているわけなのですが、はっきり言ってそれではつまらなくないですか?
お互い人間なわけですから、もっと人間らしい交流をしたいですよね。
だからこのスタイルでPerl/CGI講座をしているんです。
ただ情報が並んでいるだけの無味乾燥ページにはしたくないんです。
そんなことをしては、わざわざこうして続けている意味ないんです。
あなたもわざわざ、このページで学習する意味ないわけですよ。
これでは、お互いつまらないですし、学習そのものが中途半端になってしまうと思うんですよ。
そんなのイヤなので、書くべき時に書くべきことを書いているわけです。
だから、このPerl/CGI講座の記事は長くなってしまうというわけです(笑)。
次に、たくさんあるPerl/CGIプログラミング学習教材への不安というのがあります。
たくさんあるPerl/CGIプログラミング学習教材の中には、ものすごくいいかげんなものも存在します。
そんな教材で学習するぐらいなら、このホームページの方がよっぽど役に立つと思っています。
そんな思いがあるのでこのPerl/CGI講座の記事は長くなってしまうわけです。
あなたが、Perl/CGIプログラミングを学習していこうと思った理由はいろいろあると思います。
なんとなく。
転職やスキルアップなど仕事で必要だから。
趣味で何か作ってみたいから。
どんな理由があろうとも、このサイトと巡り合ったわけですから、一緒に学習していきましょう!
で、ここまで長々書いてきていったい何が言いたいのかというと…。
それは、このPerl/CGI講座はこれからも長いままでいきますよということです。
今、読者さんの半分ががっかりしたため息をつき、もう半分が心の中で安心したような空気を感じましたが、間違いでしょうか(苦笑)。
まぁ、なんにしてもそういうことですから、これからもがんばっていきましょう!
それでは今回の学習に移っていきましょう。
split関数の基礎
それでは、 Perl/CGIプログラミング におけるsplit関数について学習していきましょう。
splitとは、英単語の意味そのままで、何かを切り離すとか分割するとか言う意味です。
特にsplitは、強制的に切り離すといったニュアンスがあります。
ですから、Perl/CGIプログラミングでのsplit関数も、何らかの値を切り離すときに使います。
ここでの値というのは、主に文字列のことです。
split関数とは、与えられた文字列を、指定した文字または文字列で分離させる関数だと覚えておいてください。
使い方もそんなに難しくありません。
split関数の使い方
それでは、split関数の使い方を見ていきましょう。
「分割された文字列 = split(/区切り文字/, 指定文字列, 分割数)」split関数の使い方の基本形はこんな感じです。
「分割された文字列」は、 配列 または、配列状に並んだ スカラ変数 がきます。
スカラ変数を配列状に並べて受け取る場合は、分割された数の分だけ変数を用意しておくとよいですね。
一方、配列で受け取っておくと、分割された数の分だけ要素が自動的に作成されるので、細かいことを気にしなくてすみます。
「区切り文字」は、その後ろにある「指定文字列」を区切る基準となる文字または文字列がきます。
区切り文字には直接文字を使用する以外にも、その文字に該当する16進コードなども使えます。
ですから、空白文字やタブ、改行コードなども指定することができます。
さらに、直接区切り文字を指定しなくても、その文字をパターンで指定することもできます。
Perl/CGIプログラミング用語では、パターンマッチといったりしますが…。
そのパターンマッチを使って、文字列を分割することもできます。
「指定文字列」は、分割される文字列がきます。
場合によっては省略することもできます。
例えば ループ処理 などで、指定文字列が特殊変数「$_」に格納されている場合は省略できます。
「分割数」は、そのままの意味で分割数を指定できます。
これも省略することができます。
省略された場合は、「区切り文字」に該当する部分で可能な限り分割されます。
これで、split関数の基本的な書式とその解説は以上です。
わからないところがいくつかあったと思いますが、後で詳しく解説していきますから、今は適当に流しておいてください。
split関数で文字を基準に区切る
それでは実際にsplit関数を使って、文字列を区切り文字で分解していきましょう。
#!/usr/bin/perl
use strict;
print "Content-type: text/html\n\n";
my $line = 'Yamada,Tarou,tarou@yamada.com,';
my @parts = split(/,/, $line);
for (my $i=0;$i<=$#parts;$i++) {
print "$i : $parts[$i]";
print "<br>\n";
}
exit;
このPerl/CGIプログラムを実行すると…。
0 : Yamada
1 : Tarou
2 : tarou@yamada.com
こんな感じで表示されます。
この例では、CSV形式のデータからsplit関数を使って、各要素を取り出すということをしています。
CSV形式とは、各項目が「,」で区切られているテキスト形式のデータのことです。
ちなみにCSVとは、「Comma Separated Values」の略です。
Perl/CGIプログラムの世界では、外部ファイルにデータを記録する際、このCSV形式にして保存する場合があります。
そうなるともちろん、外部ファイルのデータを読み込むときは、CSV形式のデータを扱うことになります。
そんなときは、今回のようにカンマを区切り文字としたsplit関数を使うことで、各項目を取り出すことができます。
そのsplit関数は、以下の部分で使われています。
「my @parts = split(/,/, $line);」
変数「$line」内の文字列「Yamada,Tarou,tarou@yamada.com,」に対して、split関数で「,」を区切り文字として可能な限り分割し、配列「@parts」に代入させています。
念のために書いておきますが…。
区切り文字は「/」にはさまれている「,」ですからね。
「/,/」部分の「,」が区切り文字で、2つ目の「/」の直後にある「,」は、split関数への引数の区切りをあらわしているだけなので、そのあたりを間違えないようにしてくださいね。
なんだかややこしいですが(苦笑)。
そんなこんなで、split関数によって処理されると、配列「@parts」の各要素は以下のようになるわけです。
要素番号「0」には「Yamada」。
要素番号「1」には「Tarou」。
要素番号「2」には「tarou@yamada.com」。
このとき「,」は区切り文字として扱われているので、基本的にはすべて取り除かれます。
ただし、実際に分割できる数が指定した分割数を上回っている場合には、区切り文字が一部無視されます。
split関数で分割数を指定する
ここでは、分割数を指定してsplit関数を使う方法について解説します。
先ほどのPerl/CGIプログラムを改造して、split関数の文字列分割に制限をかけてみます。
たとえばこんな感じです。
#!/usr/bin/perl
use strict;
print "Content-type: text/html\n\n";
my $line = 'Yamada,Tarou,tarou@yamada.com,';
my @parts = split(/,/, $line, 2);
for (my $i=0;$i<=$#parts;$i++) {
print "$i : $parts[$i]";
print "<br>\n";
}
exit;
split関数の使用部分で、新たに分割数「2」を指定しました。
それ以外は変わっていません。
このPerl/CGIプログラムを実行させると、以下のように表示されます。
0 : Yamada
1 : Tarou,tarou@yamada.com,
分割数で2が指定されたため、配列「@parts」の要素数も2つとなります。
そして、2つ以上には分割されませんから、2つ目の要素には区切り文字や、3つ目に分割されるはずの文字列がそのままの状態でくっついています。
split関数で文字列を基準に区切る
今度もsplit関数を使って文字列を分割していきますが、ここでは、分割する基準を文字ではなく文字列にしてみましょう。
#!/usr/bin/perl
use strict;
print "Content-type: text/html\n\n";
my $line = 'Yamada<>Tarou<>tarou@yamada.com<>';
my @parts = split(/<>/, $line);
for (my $i=0;$i<=$#parts;$i++) {
print "$i : $parts[$i]";
print "<br>\n";
}
exit;
このPerl/CGIプログラムを実行すると、以下のように表示されます。
0 : Yamada
1 : Tarou
2 : tarou@yamada.com
区切り文字が「<>」に変わっただけで、あとは、分割数を指定しなかった一番最初の例と同じ結果になりました。
変数「$line」に代入する文字列の「,」部分をすべて、「<>」に変更し…。
それにあわせて、split関数の区切り文字も「,」ではなく、「<>」に変更しました。
それ以外は一番最初のPerl/CGIプログラム例のままです。
区切り文字が一文字の「,」でも、複数の文字である文字列の「<>」でも、同じことができるというのがわかりましたね。
これで、split関数の基本的な使い方の解説は以上です。
あと、ここまで何気にsplit関数の区切り文字をすべて記号にしてきましたが、アルファベットや数字も使えますからね。
例題が偏っているだけですから(苦笑)。
split関数の区切り文字にはむしろ、記号よりもアルファベットや数字を使ったほうが安全です。
なぜなら、記号には一部特殊な意味を持ったものがあり、それを知らずにsplit関数を使ってしまうと、文字列が思うように分割されなくなるからです。
次は、そんな注意すべき記号と、その扱い方について学習していきましょう。
split関数の注意
ここでは、Perl/CGIプログラミングでsplit関数を使っていく上で、注意すべき点についてみていきましょう。
先ほどsplit関数の区切り文字には、アルファベットや数字を使うぶんには問題ないが、記号を使うときには、一部注意しなくてはいけないものがあると書きましたよね。
ここではそのあたりを具体的にみていきます。
split関数の区切り文字に使用する記号で注意すべきものというのは、大きく分けて2パターンあります。
1つ目は、区切り文字自体が、それをはさんでいる記号と同じになっている場合。
2つ目は、区切り文字自体が、正規表現で使用する記号だった場合。
それぞれ具体的にみていきましょう。
区切り文字がはさまれている記号と同じ場合
まずは一つ目、split関数の区切り文字が、それをはさんでいる文字と同じだった場合には、特別な処理が必要です。
どういうことかというと、例えば、split関数の区切り文字というのは、「/」ではさまれていましたよね。
このとき区切り文字も「/」だった場合には、「///」と書いてはいけませんよという話です。
仮に「///」と書いてしまうと、区切り文字なしで、最後の「/」はプログラミングミスだと判断されてしまいます。
このような現象を回避するには、大きく分けて3つのやり方があります。
1つ目は、区切り文字をはさんでいる文字を変更し、区切り文字と重複しないようにする方法。
2つ目は、区切り文字にエスケープ記号を付加して、それをはさんでいる文字と区別する方法。
3つ目は、区切り文字をコードで記述し、それをはさんでいる文字と区別する方法。
ひとつひとつ解説していきますね。
区切り文字をはさんでいる文字を変更する方法
そもそも、区切り文字をはさんでいる文字と区切り文字が同じだから問題が起こるわけです。
ならば、区切り文字をはさんでいる文字を変えてしまえばよいという発想ですね。
#!/usr/bin/perl
use strict;
print "Content-type: text/html\n\n";
my $string = 'Perl/CGI';
my @parts = split(m|/|, $string);
for (my $i=0;$i<=$#parts;$i++) {
print "$i : $parts[$i]";
print "<br>\n";
}
exit;
このPerl/CGIプログラムを実行すると、以下のように表示されます。
0 : Perl
1 : CGI
本来、区切り文字をはさんでいる文字は「/」ですが、それを「|」に変更し、区切り文字に「/」を指定して、文字列を分割しています。
区切り文字をはさんでいる文字を変更するには、最初に「m」をつけ、その直後に変更した文字で区切り文字をはさむようにします。
「my @parts = split(m|/|, $string);」という部分がそうですね。
ここでは「|」に変更していますが、「\」にしたい場合は、「my @parts = split(m\/\, $string);」となります。
区切り文字にエスケープ記号を付加する方法
二つ目は、区切り文字とそれをはさんでいる文字が同じだった場合、区切り文字に印をつけ、それをはさんでいる文字と区別しましょうという発想ですね。
具体的には、区切り文字の直前にエスケープ記号の代名詞「\」をつけます。
Perl/CGIプログラミングで、「\」が出てきた場合、それはほぼ特別な何かをあらわしていますから、注意する癖をつけておきましょう。
#!/usr/bin/perl
use strict;
print "Content-type: text/html\n\n";
my $string = 'Perl/CGI';
my @parts = split(/\//, $string);
for (my $i=0;$i<=$#parts;$i++) {
print "$i : $parts[$i]";
print "<br>\n";
}
exit;
このPerl/CGIプログラムを実行すると、以下のように表示されます。
0 : Perl
1 : CGI
split関数を使っている部分は「my @parts = split(/\//, $string);」ですね。
区切り文字「/」の前に「\」を記述したことにより、区切り文字をはさんでいる「/」とは区別して扱われました。
これは、単純に「\」を頭につけるだけですから手軽にできますよね。
区切り文字をコードで表現する方法
最後は、区切り文字自体をコードで表現し、区切り文字をはさんでいる文字と区別させる方法です。
Perl/CGIでは、プログラム中の文字や文字列を、16進数などのコードで表現することができます。
なので区切り文字「/」を、16進数に置き換えて区別しましょうというのが今回の発想です。
例えばこんな感じです。
#!/usr/bin/perl
use strict;
print "Content-type: text/html\n\n";
my $string = 'Perl/CGI';
my @parts = split(/\x2F/, $string);
for (my $i=0;$i<=$#parts;$i++) {
print "$i : $parts[$i]";
print "<br>\n";
}
exit;
このPerl/CGIプログラムを実行すると、以下のように表示されます。
0 : Perl
1 : CGI
区切り文字「/」と、区切り文字をはさんでいる文字「/」とを区別するために、区切り文字「/」を、16進数「\x2F」で表現しています。
「my @parts = split(/\x2F/, $string);」という部分がそうですね。
Perl/CGIプログラム中で16進数を使うためには、「\x」を頭につけ、その後に16進数を記述していきます。
このあたりを詳しく書いていると、とんでもない量になってしまうので、また別の機会に説明しますね。
そもそも「16進数って何だよ?」っていう人もいると思いますので…。
とりあえず今は、区切り文字「/」は、16進数「\x2F」に書き換えることができるということを覚えておいてください。
ほかの 文字を16進数に変換したい場合には、こちらのページ を参照してください。
以上3つが、区切り文字とそれをはさんでいる文字とが同じだった場合の対処法です。
ここまでが、split関数を使う上で注意すべき点のひとつ目とその対処法です。
区切り文字が正規表現文字だった場合
split関数を使う上での2つ目の注意点は、区切り文字が正規表現で使用する文字だった場合です。
その場合は、区切り文字としてではなく、正規表現だと解釈され意味が変わってしまいます。
「正規表現」を見ただけでなんだかやる気をなくす人や、頭を抱えてしまう人がいますが、今回はほんの少ししか出てきませんからご安心を…。
初めて正規表現という言葉を聞いたという人のために説明しますと…。
正規表現とは、文字列の特徴を表現するために列挙される記号や文字のことです。
これだけ読んでも何のことだかわかりませんよね。
というか、正規表現という日本語自体、何なんだという突っ込みを入れたくなりますよね(苦笑)。
まぁ、言葉自体がわかりにくいわけですから、正規表現を実際に見ても一度では理解しづらいわけですが…。
それゆえに、正規表現を理解できるかどうかというところが、Perl/CGIプログラミングを学習していく上での山のひとつになっています。
まぁでも今回は、正規表現といってもさわりの部分しか出てきませんから、簡単ですよ。
例えば、「.」という記号がありますよね。
この「.」というのは、正規表現では「何か1文字」を表す記号として使われています。
何か1文字ですから、AやB、1でも2でもそれが1文字であればそれを「.」に置き換えて表現できるようになっています。
「.」は何か1文字ですから、「..」と書けば何か2文字で、「...」と書けば何か3文字をあらわすことになります。
このあたりの詳しい解説は正規表現の学習でじっくりやりますので、今は「.」は「何か1文字をあらわすもの」だと覚えておいてください。
ここまではいいですよね。
では、ここからが本題です。
この「.」というのは、そのままではsplit関数の区切り文字として使うことはできません。
なぜなら先ほど説明しましたように、「.」というのは正規表現上の意味「何か1文字をあらわす」という意味に解釈されてしまうからですね。
まぁそれでもよいのであれば問題ないのですが…。
少なくとも、「.」そのものを意図したいときには困りますよね。
そんなときは、もうお気づきかもしれませんが、「\」の力を借ります。
「.」の直前に「\」を付け、正規表現的解釈をはずします。
#!/usr/bin/perl
use strict;
print "Content-type: text/html\n\n";
my $string = 'google.com';
my @parts = split(/\./, $string);
for (my $i=0;$i<=$#parts;$i++) {
print "$i : $parts[$i]";
print "<br>\n";
}
exit;
このPerl/CGIプログラムを実行すると、以下のように表示されます。
0 : google
1 : com
文字列「google.com」が、「.」で分割されましたね。
仮に「my @parts = split(/\./, $string);」ではなくて…。
「my @parts = split(/./, $string);」のように「\」をはずしてしまった場合には、何も表示されなくなるか、エラー画面が表示されます。
ここまできたついでにもうひとつ、「.」を「何か1文字」という意味で使う場合について学習しておきましょう。
例えばこんな感じで使います。
「my @parts = split(/g./, $string);」
こうすると、区切り文字が「g○」つまり、「g」と「g直後の何か1文字」となります。
ようするに、文字列は「google.com」ですから、「go」と「gl」が区切り文字になるわけです。
そして実行結果は…。
0 :
1 : o
2 : e.com
簡単ですよね。
ひとつ目の要素番号「0」には何も書かれていないのは?
split関数は、ひとつの文字列を、ふたつ以上に分断する関数だからですね。
つまり、文字列の最初の文字が、いきなり分割基準の文字に該当するものですから、空の値を作って無理やりですが、分断したという体裁をととのえているというわけです。
これで、split関数を使用する上での注意点は以上です。
<戻る>
split関数の応用
ここでは、split関数とパターンマッチを組み合わせたPerl/CGIプログラミングを学習していきましょう。
パターンマッチとは、読んで字のごとく、文字のパターンを提示し、それにマッチするかどうかを判断させる方法のことです。
正規表現を駆使して、文字列の雰囲気を表現する手法といったほうがわかりやすいでしょうか…。
先ほどは、「.」が何らかの1文字を現すという性質を利用したsplit関数プログラミングを紹介しましたが、ここではもう少し具体的に、文字の種類を限定させる方法について見ていきます。
例えば…。
#!/usr/bin/perl
use strict;
print "Content-type: text/html\n\n";
my $line = 'P1e2r3l4/5C6G7I8';
my @chars = split(/[0-9]/, $line);
print @chars;
exit;
このPerl/CGIプログラムを実行すると「Perl/CGI」と表示されます。
数字がすべて消えましたね。
split関数で消えたということは、数字がすべて区切り文字扱いされたということです。
split関数部分は「my @chars = split(/[0-9]/, $line);」この中でも区切り文字を指定している部分は…。
「[0-9]」ですよね。
この「[0-9]」という部分で、「0」から「9」までの数字を指定しています。
仮に、「[2-5]」だった場合には、「2」から「5」までとなります。
「○から○まで」というのは、まず、「[」と「]」で値の並び全体をくくります。
そして、その開始位置と終了位置を「-」でつなぐことにより、その間の値も表現していることになります。
もし、「[」と「]」ではさまなかった場合は「0」から「9」までの数字ではなく、「0-9」という文字列自体が区切り文字として扱われてしまいます。
このあたりはわかりやすいですよね。
それでは今度は逆に、数字だけを残すにはどうしたらよいと思いますか?
つまり、「Perl/CGI」ではなく、「12345678」と表示させるにはどうすればよいかということです。
正解を書きたいのですが、紙面上きつくなってきましたので、今回はここまで…。
ぜひ考えてみてください。
編集後記
あっという間に記念すべき10回目も終了です。
いやー、もっと書いておきたいことはいろいろあるんですが…。
紙面の限界には逆らえません(苦笑)。
それはそうと、はじめて正規表現やパターンマッチに触れた場合は、何度か復習しておいてくださいね。
これらは、Perl/CGIプログラミング独特の感覚みたいなものがあります。
慣れるまでは少し時間がかかるということです。
たくさん接して早く慣れておくことがポイントです。
それではこの辺で、今回の学習は以上です。
ありがとうございました。
<戻る>