T

PHPのsplit関数

Ruby、Perl、Pythonのsplit関数の挙動をまとめたページをつらつらと読んでいたのだが、そういえばPHPはどうなっているか気になったのでちょっと試してみた。

まずPHPのsplit関数だが、マニュアルによれば

説明
array split ( string $pattern , string $string [, int $limit ] )

string を、正規表現によって配列に分割します。

となっている。つまり、splitの第一引数は正規表現しかない。

$str = "a,b,c";
print_r(split(",", $str));
/*当然下のようになる。
Array
(
    [0] => a
    [1] => b
    [2] => c
)
*/

$str = "a,,c,,";
print_r(split(",", $str));
/* 末尾の空要素は無視されない。
Array
(
    [0] => a
    [1] => 
    [2] => c
    [3] => 
    [4] => 
)
*/

$str = "";
print_r(split(",", $str));
/* 空文字を分割すると空の配列が返る
Array
(
    [0] => 
)
*/

$str = "";
print_r(split("", $str));
/*
分割パターンが空だとエラーになって実行できない。
*/

$str = "a:b;c.d";
print_r(split("\.", $str));
/* 文字列では指定できないので意地になってみる。
Array
(
    [0] => a:b;c
    [1] => d
)
*/

$str = "a:b;c.d";
print_r(split("[:;.]", $str));
/* 正規表現だから範囲指定で。
Array
(
    [0] => a
    [1] => b
    [2] => c
    [3] => d
)
*/

$str = "a.b.c";
print_r(split("[.]", $str));
/* これも同じ。
Array
(
    [0] => a
    [1] => b
    [2] => c
)
*/

$str = "a;b;c";
print_r(split(":", $str));
/* どれにもマッチしない。
Array
(
    [0] => a;b;c
)
*/

と、まあここまではいい。正規表現なのか文字列なのか区別がないので、正規表現しか受け付けないという潔さも、まあいいだろう。文字列が使いたいならexplodeすればいいじゃない、と王妃もおっしゃってましたし。

ところが、納得できないのはこれだ。

$str = "a.b.c";
print_r(split(".", $str));
/* 全部空文字で返ってきたよ。。。
Array
(
    [0] => 
    [1] => 
    [2] => 
    [3] => 
    [4] => 
    [5] => 
)
*/

$ret = split(".", $str);
var_dump($ret);
/* 文字列だって言い張るんだよ。。。
array(6) {
  [0]=>
  string(0) ""
  [1]=>
  string(0) ""
  [2]=>
  string(0) ""
  [3]=>
  string(0) ""
  [4]=>
  string(0) ""
  [5]=>
  string(0) ""
}
*/

直感的には、空の配列かFALSEが返ってくるような気がするのだが、こういうことらしい。ううむ。

Posted by on 9月 8, 2008 in PHP

Comments

  • アンチだけど擁護します より:

    $str=”,,,,,”; split(“,”, $str);
    と同じものが返ってきているのなら、納得じゃないですか?
    Rubyがこの場合に空配列を返すのは末尾の空文字列の要素を削除するから(だと考えられる)なので PHPには当てはまらないし……。

  • admin より:

    アンチどころかPHPは生活の糧ですが、確かにそういわれてみると納得できますね。

  • ccn1x より:

    (PHPのパフォーマンスについて調べてたら辿り着いたものです)
    すべて空文字列で6要素というのは、正常な動作だと思うのですが。
    split(“.”, “a.b.c”)は、任意の1文字を区切り文字にするわけですよね?
    だから最初はaが区切り文字となって、aの直前のもの(無いので空)が結果の配列の1つめにセットされる。
    次に.(一個目)が区切り文字になって、直前の区切り文字aと.(一個目)の間にあるもの(無いので空)が配列の2つ目に。
    以後同様にセットされてき、最後はcと文字列末端の間(やっぱり空)がセットされる、こういう動作だと思います。
    各区切り文字の間が0バイト(空)で、区切り文字が5つある、とみなせば、出力も6つであってますし。

    趣味の範囲でやっている者なので、間違ってたら本当申し訳ないです…。

  • admin より:

    > ccn1x

    はい、まったくそのとおりだと思います。直観に反すると思ったので上のように書いています。直観というのは、単純に区切り文字はワイルドカードなので、何もないところで文字列を区切ってaと.とbと.とcで返してくれないかなあ、と思うという意味です。

  • ccn1x より:

    なるほど。
    自分の直感としてはsplit(“”, $str)だと思いました、見事にエラーと言われましたが…。
    環境がPHP5なら、str_split関数が希望の動作をするのではないかと思います。
    PHP4なら(調べた限りでは)自前でループ回すなりして実装するしかない気がします。

    最初の投稿のときに書くべきでしたが、二ヶ月も前の記事にコメントして申し訳ありませんでした。

  • admin より:

    むしかえしは歓迎します。(参照:http://d.hatena.ne.jp/m-hiyama/)

  • コメントを残す