あーる学習帳

自分が勉強したことや気になることなど、99%自分用です。コードを書いてるのでPCから閲覧を推奨。

PHP実習:正規表現と文字列の置き換え、違反ワードをチェックする機能を作ろう

今夜も正規表現について学んでいこう。

 

第9章-04

今回は文字列の操作について学ぶ。クライアントからの入力値には空白や全角英数字などプログラムにとって不都合な文字が含まれている場合がある。そのようなときは文字列を操作しなければならない。

文字列の前後に「スペース」や「タブ」が入ってしまっている場合、それを取り除くための関数が用意されている。

trim()...文字列の両端の空白を削除

rtrim()...文字列の右端の空白を削除する

ltrim()...文字列の左端の空白を削除する

chop()...ltrim()と同じ意味 

chop()はltrim()のエイリアスである。 エイリアスとは名前だけを変えて昨日は同じものという意味。

trim()で取り除ける空白文字とは何を意味するのか、実際のコードで確認。

<?php
 $str1=' AB C '; // 文字列の前後に半角スペース
 $str2=' こんにちは '; // 文字列前にタブ2つ、後ろに全角スペース
 $result1=trim($str1);
 $result2=trim($str2);
 var_dump($result1);
 var_dump($result2); 

 出力結果は、「string(4) "AB C" string(18) "こんにちは "」となる。

前後に削除対象の文字列があればすべて取り除くことが分かるが、全角スペースは取り除けない。trim()の削除対象となるのは、半角空白、タブ、リターン、改行、Nullバイトなどである。

 

PHPにおける「mb」とはマルチバイトのことである。半角英数が1文字1バイトなのに対し、文字コードUTF-8における日本語は基本的に1文字に付き3バイトほどあるのでそのように呼ばれる。

mb系組み込み関数の代表的なものを以下に挙げる。

mb_strlen()...文字列の長さを得る

mb_strtolower()...文字列を小文字にする

mb_convert_encoding()...文字エンコーディングを変換する

mb_language()...現在の言語を設定あるいは取得する

mb_substr()...文字列の一部を得る

mb_convert_kana()...カナを変換する(全角と半角の変換)

mb_strpos()...指定した文字列が最初に現れる位置を探す 

この中で、mb_convert_kana()についてサンプルコードで学ぶ。

<?php
 $str1='KV:プログラミング';
 $str2='as:私はMOVIEが 好きです。';
 $result1=mb_convert_kana($str1,'KVas','UTF-8');
 $result2=mb_convert_kana($str2,'KVas','UTF-8');
 var_dump($result1);
 var_dump($result2);

それぞれオプションに「KV」「as」を設定して効果を確認する。

戻りとして「string(24) "KV:プログラミング" string(33) "as:私はMOVIEが 好きです。"」と画面に表示される。

mb_convert_kana()の第2引数には複数の変換オプションを指定することが可能である。「K」は「半角カタカナを全角カタカナに変換」「V」は「濁点付きの文字を1文字に変換(プ→プ)」を表す。もしVを指定しなかった場合、「プログラミング」は「フ゜ロク゛ラミンク゛」と表示されてしまうので、KとVはセットで運用するのがよい。「a」は「全角英数字を半角英数字に変換」「s」は「全角スペースを半角に変換」を意味する。また、他にも「n(全角数字を半角に変換)」「H(全角ひらがなを全角カタカナに変換)」などのオプションがある。

このように、データベースなどの登録前にクライアントからの入力値を最適な状態に整えることはメンテナンス上非常に大事なことである。

 

次に、文字を置き換えるコードであるpreg_replace()とstr_replace()について確認していく。preg_replace()は正規表現が使える分、str_replace()の精密版ともいえる。

<?php
 $str=' プログラミングを、習いたい。';
 $result1=preg_replace('/\s|、|。/','',$str);
 var_dump($result1); 

 これは戻りとして「string(36) "プログラミングを習いたい"」が画面に表示される。

preg_replace()は第1引数に正規表現、第2引数に置き換える文字列、第3引数に対象の文字列を入れる。今回は第1引数を「'/\s|、|。/'」とすることで、半角スペースか読点か句読点ならば「''(空の文字列)」に置き換えるという指定をしている。preg_replace()は対象の文字を置き換えた後、置き換え後の文字列を返してくる。また、str_replace()では第1引数に置き換えたい文字列を単純に指定する。

preg_replace( 正規表現 , 置き換える文字 , 対象の文字列)

str_replace( 検索する文字 , 置き換える文字 , 対象の文字列) 

 

第9章-05 実習

違反ワードをチェックする機能を作る。

制作の流れは、

  1. 検索対象の文字を整える
  2. 許可ワードを検索対象から外す
  3. 禁止ワードをチェックする

許可ワードは「*」に置き換える仕組みとする、禁止ワードの有無、置き換えた許可ワードを結果として表示する。

例:「コーヒー」を禁止ワードにした場合

禁止ワードが含まれています。ミルクコーヒー->ミルクコーヒー 

例:「パン」を禁止、「フライパン」を許可ワードにした場合

禁止ワードは含まれていません。フライパン->*

 要件定義は、

  • チェック機能を日本語に対応させる
  • 1つのワードに対して複数の禁止ワードが設定できるようにする
  • 許可ワードも設定できるようにする

まず、チェックしたいワードを検索しやすいように整えていく。

<?php
 $str='ミルクコーヒー';
 // 検索しやすいように文字列を整える
 $target=mb_strtolower($str,'UTF-8');
 $target=mb_convert_kana($target,'KVas','UTF-8');
 $target=preg_replace('/\s|、|。/','',$target);

 $flag=0;

 // 許可ワードを検索対象から外す

 // 禁止ワードをチェックする

 if ($flag>0) {
  echo "禁止ワードは含まれています。";
 } else{
  echo "問題のない文字列です。";
 }
 echo '「'.$str.'」';

英字はmb_strtolower()を使い、大文字をすべて小文字に直す。元の文字列はデータベースに登録したりするときに必要なので、$targetという変数を定義して代入する。mb_convert_kana()でオプションをKVasとすることで半角カナや全角スペースなどを取り除くことができる。さらにpreg_replaceでは正規表現を使い、半角スペースやタブなどを取り除いている。今回はフラグとして$flagを定義し、禁止ワードを見つけた場合は1を代入する。

次は許可ワードを検索対象から外す処理を考える。例えば「コーヒー」をNGにしたいが「コーヒーゼリー」は許可したい場合を考えていく。「コーヒーゼリー」という文字列は「*」に変換しておき、禁止ワード検索の時にチェックを回避するようにしておくのがよさそうである。

// 許可ワードを検索対象から外す
$ok_words= array('フライパン','コーヒーゼリー');
foreach ($ok_words as $ok_word) {
 if (mb_strpos($target,$ok_word)!==false) {
  $target=str_replace($ok_word,'*',$target);
 }

 mb_strpos()で一度許可ワードが含まれていることを確認してから、str_replaceで許可ワードを「*」に変換している。str_replace()はマルチバイトに対応していないため、一度mb_strpos()で許可ワードが含まれていることを確認しないと日本語環境では意図しない文字を変換してしまう可能性がある。mb_strpos()は対象文字が見つかった場合、最初に現れる位置を数字で返す。見つからなかった場合は「false」を返すので、これを判定に使っている。許可ワードが間違いなくあることを確認したうえで、str_replace()によって許可ワードを「*」に変換している。

では、実際に禁止ワードのチェックを行っていく。今回は禁止ワードを「パン」「コーヒー」として、1つでも見つかり次第$flagに1を代入して検索を終了させる。

// 禁止ワードをチェックする
$ng_words=array('パン','コーヒー');
foreach ($ng_words as $ng_word) {
 if (mb_strpos($target,$ng_word)!==false) {
  $flag=1;
  break;
 }

 先ほどと同じくmb_strpos()を使い、今度は禁止ワードが含まれるかをチェックしていく。見つかったらbreakでforeachの処理から抜けるようにしておく。

 

コードはこれで完成、今夜はここまで。明日余裕があればPOSTで受け取った文字列の判定を行うようにコードを組みたい。