[mb_split]日本語文字列を分割する(抽出)

公開日| 2015年4月19日   更新日| 2015年4月19日   コメントはありません。

以前に同じような「[strlen,mb_strlen]日本語の文字数を調べる」を投稿しています。今回は、日本語への対応の仕方です。
phpでは、日本語の取り扱いで、注意しておかないといけないことがあります。
しかし、Javaでは何の問題もないので、まず、それを確認しておきましょうか。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.io.Console;
 
public class split {
	public static void main(String[] args) {
		//	分割する文字列
		String str = "oneソtwoソthreeソfour";
		//	文字列を , で分割する
		String[] tokens = str.split("ソ");
		//	分割した結果をコンソールへ出力
		Console con = System.console();
		for (int i=0; i<tokens.length; i++) {
			con.printf("[%d]%s\n",i+1,tokens[i]);
		}
	}
}
C:\ > java split
[1]one
[2]two
[3]three
[4]four

と、こんな感じです。前回の記事「[strlen,mb_strlen]日本語の文字数を調べる」の日本語版です。やっていることは変わりませんが、ShiftJISで問題になりやすい「ソ」で文字列を分割しているのがミソです。。
もちろん、Javaでは、ちゃんと分割できています。

では、phpでは?

1
2
3
4
5
6
7
8
9
10
<?php
//	分割する文字列
$str = 'oneソtwoソthreeソfour';
//	文字列を , で分割する
$tokens = split("ソ",$str);
//	分割した結果をコンソールへ出力
for ($i=0; $i<count($tokens); $i++) {
	printf("[%d]%s\n",$i+1,$tokens[$i]);
}
?>
C:\>php split.php
Parse error: syntax error, unexpected '[' in C:\..\split.php on line 8

とこんな感じで、エラー発生です。

これは、一般的配布(ダウンロード)されているphpには、ShiftJISの環境が組み込まれていないためです。そのため、ほとんどの場合、phpは、UTF-8で記述されることが多いのです。

上記のエラーは、phpにmbstring が 組み込まれていないために発生します。これを回避するには、コンパイルオプションである --enable-mbstring を付けて、php自体を自分でリコンパイルする必要があります。
さらに、php.iniにてmbstring.script_encoding =SJISを指定することで、ShiftJISで記述されたphpを正しく実行できるようになります。

※一般的に配布されているWindows版phpには、この設定は組み込まれていません。

やれなくないのでしょうが、大変そうです。
php5.2でよければ、有志の方が、ShiftJIS対応のphpを配布しておられます。
※ShiftJISでphpをどうしても書かないといけない場合を除き、ShiftJISで記述すべきではないのだと思います。

そういうこともあって、phpで記述している主要なCMSでは、文字コードUTF-8を使うのが標準になっています。
もちろん、mysqlもUTF-8となります。

Linuxが標準文字コードとして使っているのがUTF-8なので親和性があるのもわかりますね。

実際に、先のコードをUTF-8で保存すれば、以下のように表示されます。

C:\>php split.php
[1]one
[2]two
[3]three
[4]four
DOSプロンプトは、基本的にShiftJISの文字列を表示するようになっています。
そのため、上記ようにUTF-8をそのままのDOSプロンプトから実行すると、
C:\>php split.php
[1]・擾ス趣ス・[2]o・費ス暦ス・[3]・費ス茨ス抵ス・ス・[4]・・ス擾ス包ス・
のように文字化けで何が表示されているかわかりません。

この場合は、「phpのUTF-8をWindowsで使えるようにする」を参考に環境を整えましょう。
ここまでで、多くの方は、ご理解いただけるかと思います。 phpは、(すくなくとも現状では)基本的にUTF-8で記述すべきで、どうしておShiftJISやEUCで出力が必要な場合は、文字コード変換してやるべきなんでしょうね。

※phpでは、javaと同じように内部処理をすべてUTF-16でやろうと試みているようですが、あまりうまくいっていないようです。やっぱし、UTF-8でしばらくやっていくんでしょうね。

使う関数は?

ここまで文字列の分割を行うための処理を考えてきました。日本語の場合は、mb_系の関数を使います。
文字列の分割には、mb_split を使うべきなんでしょうね。でも、UTF-8で記述しているなら、通常のexplode,preg_splitでも同じ結果を得ます。

ということなので、mb_splitは、ShiftJIS用みたいなものかもしれませんね。

  • array mb_split ( string $pattern , string $string [, int $limit = -1 ] )
    : マルチバイト文字列 string において、正規表現 pattern により文字列を分割し、 結果を配列として返します。

    注意:
    内部エンコーディングあるいは mb_regex_encoding() で指定した文字エンコーディングを、この関数の文字エンコーディングとして使用します。

    これ見落としがちです!!これって、ソースコードの先頭にちゃんとmb_regex_encoding()を記述しなさいってことですから、忘れずに設定しましょう。
    // 文字エンコードの設定(内部エンコードを指定しないと正しく動作しない)
    mb_regex_encoding('UTF-8');
     
    $str = 'oneソtwoソthreeソfour';
    // 文字列分割を実施
    var_dump(mb_split("ソ", $str));
    var_dump(explode("ソ", $str));
    var_dump(preg_split("/ソ/", $str));
    C:\>php mb_split.php
    array(4) {
      [0]=>
      string(9) "one"
      [1]=>
      string(10) "otwo"
      [2]=>
      string(15) "three"
      [3]=>
      string(12) "four"
    }
    array(4) {
      [0]=>
      string(9) "one"
      [1]=>
      string(9) "two"
      [2]=>
      string(15) "three"
      [3]=>
      string(12) "four"
    }
    array(4) {
      [0]=>
      string(9) "one"
      [1]=>
      string(9) "two"
      [2]=>
      string(15) "three"
      [3]=>
      string(12) "four"
    }
    $limitは、指定しない場合あるいは0以下の数値を指定した場合、すべてを分割します。
    正の値を指定した場合、その数分だけ分割して、残りは、そのまま出力します。

まあ、いろいろ調べると面白いですね。
phpの日本語などのロケールに関する対応は、他のjava,rubyなどと異なる対応の仕方ですね。
今、java,rubyと同じように内部処理でUTF-16への対応も考えられているとはいえ、なかなか難しそうです。もう少し様子見が必要でしょうが、どうも、phpは、じばらく、UTF-8で突っ走りそうですね。


コメント

口コミ・評判を投稿 :

ブラウザの JavaScriptが無効となっている場合、コメントの投稿はできません。
コメントを投稿するには、JavaScriptを有効にしてください

お名前 *

メールアドレス *
(口コミ・評判欄には、表示されませんが入力が必要です。)

サイトアドレス



  • はてなブックマークへ追加する
  • Facebookでシェアする
  • twitter でつぶやく
  • Google Plusでシェアする
  • Pocketでシェアする
ページトップへ