PHPで簡単な名簿txtファイルを正規表現
とある方から大学の課題の質問を受けましたので、その内容の解説noteを残します。なるべく詳細に解説するので、理解の手助けになれば幸いです。
課題文は以下のようなものでした。著作権や名誉毀損に当たらぬよう、本文とは少し変更していますがご了承を。
以下のテキストコード(meibo.txt)は、芸能プロダクションXに所属しているタレントの名簿である。カンマ区切りで左から名前, 性別(m:男性, f:女性), 公称年齢となっている。
名前, 性別, 公称年齢には、余分な空白は含まれないと仮定してよい(ただし、名前の中には姓・名などを区切る空白が含まれることがある)。行頭・行末・カンマの前後にも、余分な空白は含まれないと仮定してよい。
また、名前は氏・名の2語で構成されているとは限らないので、1語の場合や3語以上の場合にも対応できるようにすること。
Ashida Mina,f,9
Ayase Haruto,f,24
Fukuda Ryoko,f,28
Kameari Kazuya,m,25
Maeda Natsuko,f,22
Matsuoko Grand Prix,m,41
Nomura Sachiko,f,65
Oguri Jun,m,29
Kyarypunyupunyu,f,20
今年5月、芸能プロダクションXの女性タレントは全員
・公称年齢が21~25才の場合、実年齢よりも1才若く年齢を詐称している
・交渉年齢が26~39才の場合、実年齢よりも2才若く年齢を詐称している
ということが発覚した。
meibo.txtの名簿データを読み込んで、詐称された年齢を実返礼に訂正した上で、全員のデータを画面に表示するプログラムを作れ。
消磁するデータは1人1行で、カンマ区切りで左から名前, 性別, 実年齢とすること。
ただし、表示するタレントの順番は問わない。
では早速この課題をPHPで解決させていきましょう。
PHPで簡単な名簿を正規表現
実際に動くPHPコードは下のようになります。
// 読み込みたいファイルのパスを指定
$filepath = "./meibo.txt";
// meibo.txtから中身を変数に格納
$meibo = file($filepath);
// 配列文字列をカンマ区切りで2次元配列にする
for ($i = 0; $i < count($meibo); $i++) {
$meibo[$i] = explode(",", $meibo[$i]);
}
// 女性の実年齢を訂正
for ($i = 0; $i < count($meibo); $i++) {
if ($meibo[$i][1] == "f") {
if (21 <= $meibo[$i][2] && $meibo[$i][2] <= 25) {
$meibo[$i][2] = intval($meibo[$i][2]) + 1;
} else if (26 <= $meibo[$i][2] && $meibo[$i][2] <= 30) {
$meibo[$i][2] = intval($meibo[$i][2]) + 2;
}
}
}
// 改行コードの指定 ここではWebブラウザの改行コードを指定
$lncode = "<br>";
// 加工後のデータ配列を表示
for ($i = 0; $i < count($meibo); $i++) {
print($meibo[$i][0] . ", ");
print($meibo[$i][1] . ", ");
print($meibo[$i][2] . $lncode);
}
この課題で重要となるポイントは、以下のようなものになるかと思われます。
・txtファイルの読み込み
・読み込んだtxtファイルの2次元配列化
・2次元配列の取り扱いとデータの型
それぞれを詳細に解説していきましょう。
PHPでのtxtファイルの読み込み
今回はPHPで書いています。上記で紹介したコードで、txtファイルを読み込んでいる部分は下の箇所になります。
// 読み込みたいファイルのパスを指定
$filepath = "./meibo.txt";
// meibo.txtから中身を変数に格納
$meibo = file($filepath);
meibo.txtがあるパスを指定し、そのファイルの中身を変数に格納しています。ここでファイルは1人1行がそのまま文字列となった配列として格納されます。
print($meibo[0]); // => "Ashida Mina,f,9"
print($meibo[1]); // => "Ayase Haruto,f,24"
PHPではファイルの中身を一つの文字列として読み込む関数や、ファイルをバイト単位で読み込む関数、csvを読み込むことに長けている関数などがあるようです。ここら辺は他のCGI(PythonやPerl, Rubyなど)でも同じだと考えられますので、適したものを使用してください。
読み込んだtxtファイルの2次元配列化
次にファイルの中身を読み込んで格納した変数を2次元配列に変えます。ここが少し難しめなポイントになるかと思われます。
通常の配列は1次元配列と言われるものです。先ほど生成した1次元配列は下のようなイメージのものです。
// $meiboの中身
+-------------------+--------------------+---
| 0番目 | 1番目 |
+-------------------+--------------------+----
| "Ashida Mina,f,9" | "Ayase Haruto,f,24"|
+-------------------+--------------------+---
この配列を2次元配列に変換します。2次元配列とは、エクセルのテーブルのようなもので、行だけでなく列も持つものです。下のようなイメージだと思ってください。
// 加工後の$meibo
+------+----------------+------+-------+
| | 0番目 | 1番目 | 2番目 |
+------+----------------+------+-------+
| 0番目 | "Ashida Mina" | "f" | "9" |
+------+----------------+------+-------+
| 1番目 | "Ayase Haruto" | "f" | "24" |
+------+----------------+------+-------+
・
・
・
もし上記のような2次元配列の2行目の0列目を出力すると...
print($meibo[2][0]); // => "Ayase Haruto"
このように配列を加工するには、1次元配列のそれぞれの要素をカンマ区切りで配列に変換することで実現することができます。カンマ区切りをするにはPHPではexplode関数を使用します。先ほど紹介したコードの下の部分に当たります。
// 配列文字列をカンマ区切りで2次元配列にする
for ($i = 0; $i < count($meibo); $i++) {
$meibo[$i] = explode(",", $meibo[$i]);
}
// 一つの文字列が配列になる "Ashida Mina,f,9" => "Ashida Mina" , "f", "9"
2次元配列の取り扱いとデータの型
最後に加工した2次元配列を、適切なデータに加工します。課題文は以下のような部分をコードで実行します。
今年5月、芸能プロダクションXの女性タレントは全員
・公称年齢が21~25才の場合、実年齢よりも1才若く年齢を詐称している
・交渉年齢が26~39才の場合、実年齢よりも2才若く年齢を詐称している
ということが発覚した。
これは、コードでは下の部分で実現しています。
// 女性の実年齢を訂正
for ($i = 0; $i < count($meibo); $i++) {
if ($meibo[$i][1] == "f") {
if (21 <= $meibo[$i][2] && $meibo[$i][2] <= 25) {
$meibo[$i][2] = intval($meibo[$i][2]) + 1; // データの方に注意
} else if (26 <= $meibo[$i][2] && $meibo[$i][2] <= 30) {
$meibo[$i][2] = intval($meibo[$i][2]) + 2;
}
}
}
初めの加工した$meibo配列の要素(列)の数だけforループし、その次の$meiboの1行目(性別)が"f"(女性)だった場合に年齢の訂正を行なっています。この部分は2次元配列の理解ができていればそこまで難しくない内容かと思われます。
一つ注意しなければならないのが、$meibo配列のそれぞれの要素のデータ型が文字列であることです。1 + 1 = 2の演算をするのは文字列型ではなく整数型のデータ同士でなければなりませんので、年齢の部分を整数型に変更してから+1や+2の演算を行なっています。
加工した2次元配列の要素を出力
最後に加工し終わった2次元配列を出力します。これは以下の部分にあたります。
// 改行コードの指定 ここではWebブラウザの改行コードを指定
$lncode = "<br>";
// 加工後のデータ配列を表示
for ($i = 0; $i < count($meibo); $i++) {
print($meibo[$i][0] . ", ");
print($meibo[$i][1] . ", ");
print($meibo[$i][2] . $lncode);
}
ここではWebブラウザーの改行コードである<br>を使っています。この部分は適宜変えてください。
以上になります。このnoteに関するご不明の点や質問などがあれば、コメント欄にてお願いします。
この記事が気に入ったらサポートをしてみませんか?