preg_splitで複雑な区切りをさばく
preg_split とは、区切りを正規表現で指定して文字列を分割する関数です。複数種類の区切りや、揺れのある入力を柔軟にさばけます。
explodeで足りないとき
単一の区切り文字なら explode で十分ですが、「カンマでもセミコロンでも空白でも区切りたい」といった複数区切りには preg_split が向いています。区切りを正規表現で書けるので、揺れのある入力を柔軟にさばけます。
$input = 'apple, banana; cherry grape';
$parts = preg_split('/[,;\s]+/', $input);
// ['apple', 'banana', 'cherry', 'grape']
[,;\s]+ のように「+」で連続する区切りをまとめて1つと見なすのがコツで、こうすると余分な空要素が出にくくなります。
フラグで空要素を除く・位置を得る
第4引数にフラグを渡せます。よく使うのは PREG_SPLIT_NO_EMPTY で、空文字の要素を結果から除いてくれます。先頭や末尾に区切りがあると空要素が生まれがちなので、これを付けておくと後処理の array_filter が要らなくなります。
$s = ',a,,b,';
var_dump(preg_split('/,/', $s));
// ['', 'a', '', 'b', ''] 空要素だらけ
var_dump(preg_split('/,/', $s, -1, PREG_SPLIT_NO_EMPTY));
// ['a', 'b'] すっきり
第3引数の limit は explode と同じく分割回数の上限です。-1 を渡すと無制限で、フラグだけ指定したいときの定番の書き方ですね。
区切り自体を残す、一文字ずつに割る
PREG_SPLIT_DELIM_CAPTURE を使い、区切りをキャプチャグループにすると、区切り文字も結果に含められます。数式を演算子ごと分解したいときなどに便利です。また、パターンを空にマッチさせれば一文字ずつの分割もできますが、マルチバイトでは mb_str_split のほうが安全です。
// 演算子を残して分割
$expr = '3+4*2';
$tokens = preg_split(
'/([+\-*\/])/',
$expr,
-1,
PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
);
// ['3', '+', '4', '*', '2']
// 位置情報も欲しいなら PREG_SPLIT_OFFSET_CAPTURE
$with_pos = preg_split('/\s+/', 'a b', -1, PREG_SPLIT_OFFSET_CAPTURE);
まとめ
preg_split は複数区切りや揺れのある入力を分割するときの主力で、区切りを「+」でまとめる書き方と NO_EMPTY フラグを組み合わせると、無駄な空要素のない配列がきれいに得られます。区切りを残したいなら DELIM_CAPTURE、と用途に応じてフラグを選べば、explode では届かない分割が素直に書けると思います。
よくある質問
Q. explode とどう使い分けますか?
A. 区切りが単一文字なら explode、カンマでも空白でも区切りたいなど複数の区切りには preg_split が向いています。
Q. 空要素を出したくありません。
A. 第4引数に PREG_SPLIT_NO_EMPTY を渡すと空文字の要素が除かれ、array_filter での後処理が要らなくなります。
Q. 区切り文字自体も結果に残したいです。
A. 区切りをキャプチャグループにして PREG_SPLIT_DELIM_CAPTURE を付けると、区切り文字も配列に含められます。