preg_match()の使い方を調べたのでメモ
正規表現をつかって文字列を分割して、
かつどんな文字列で分割したのかも知りたかった。
やりたかったこと
// これを
$array = [
'foo_foo_1' => 'f1',
'bar_bar_1' => 'b1',
'hoge_hoge_1' => 'h1',
'foo_foo_2' => 'f2',
'bar_bar_2' => 'b2',
'hoge_hoge_2' => 'h2',
'foo_foo_3' => 'f3',
'bar_bar_3' => 'b3',
'hoge_hoge_3' => 'h3',
// ...繰り返し
'foo_foo_n' => 'fn',
'bar_bar_n' => 'bn',
'hoge_hoge_n' => 'hn',
];
// こんな感じにしたかった
$array = [
1 => [
'foo_foo' => 'f1',
'bar_bar' => 'b1',
'hoge_hoge' => 'h1'
],
2 => [
'foo_foo' => 'f2',
'bar_bar' => 'b2',
'hoge_hoge' => 'h2'
],
3 => [
'foo_foo' => 'f3',
'bar_bar' => 'b3',
'hoge_hoge' => 'h3'
],
// ...繰り返し
n => [
'foo_foo' => 'fn',
'bar_bar' => 'bn',
'hoge_hoge' => 'hn'
],
];
つまり、foo_foo_nをfooとnに分割したい。(nは整数)
とりあえずやってみる
matches を指定した場合、検索結果が代入されます。 $matches[0] にはパターン全体にマッチしたテキストが代入され、 $matches[1] には 1 番目のキャプチャ用サブパターンにマッチした 文字列が代入され、といったようになります。
よくわからないけど
第3引数を指定すると検索結果が代入されるらしい。
$str = 'foo_foo_1';
preg_match('/_[\d]/u', $str, $matches);
var_dump($matches);
// array(1) {
// [0]=> string(2) "_1"
// }
分割に使用した文字列は取得できた。
$matches[0]しか代入されてないけど。
分割された後の文字列も取得したい
$str = 'foo_foo_1';
$bar = preg_match('/(\w+)_[\d]/u', $str, $matches);
var_dump($matches);
// array(2) {
// [0]=> string(9) "foo_foo_1"
// [1]=> string(7) "foo_foo"
// }
正規表現を()で囲むと$matches[0],$matches[1]に代入された。
$matches[0] // 元の文字列
$matches[1] // ()で囲んだ正規表現にマッチした文字列
"_1"が消えてしまった。
()で囲まないと正規表現全体にマッチした文字列が$matches[0]に代入されて、
()で囲むと上記のような結果が得られるみたい。
$str = 'foo_foo_1';
$bar = preg_match('/(\w+)_([\d])/u', $str, $matches);
var_dump($matches);
// array(3) {
// [0]=> string(9) "foo_foo_1"
// [1]=> string(7) "foo_foo"
// [2]=> string(1) "1"
// }
欲しい結果を取得できた。
ただ$matches[1]や$matches[2]では使いづらい。
$matchesのキーに名前を指定できるようなのでやってみた。
$matchesのキーに名前を指定する
$str = 'foo_foo_1';
preg_match('/(?P<name>\w+)_(?P<num>[\d]+)/u', $str, $matches);
var_dump($matches);
// array(5) {
// [0]=> string(9) "foo_foo_1"
// ["name"]=> string(7) "foo_foo"
// [1]=> string(7) "foo_foo"
// ["num"]=> string(1) "1"
// [2]=> string(1) "1"
// }
やりたかった処理の実装
$array = [
'foo_foo_1' => 'foo1',
'bar_bar_1' => 'bar1',
'hoge_hoge_1' => 'hoge1',
'foo_foo_2' => 'foo2',
'bar_bar_2' => 'bar2',
'hoge_hoge_2' => 'hoge2',
'foo_foo_3' => 'foo3',
'bar_bar_3' => 'bar3',
'hoge_hoge_3' => 'hoge3',
'foo_foo_10' => 'foo10',
'bar_bar_10' => 'bar10',
'hoge_hoge_10' => 'hoge10',
'foo_foo_101' => 'foo101',
'bar_bar_101' => 'bar101',
'hoge_hoge_101' => 'hoge101',
];
$result = [];
foreach ($array as $key => $value) {
if(preg_match('/(?P<name>\w+)_(?P<num>[\d]+)/u', $key, $matches)) {
$k = (int)$matches['num'];
$result[$k][$matches['name']] = $value;
}
}
var_dump($result);
/*
array(5) {
[1]=>
array(3) {
["foo_foo"]=>
string(4) "foo1"
["bar_bar"]=>
string(4) "bar1"
["hoge_hoge"]=>
string(5) "hoge1"
}
[2]=>
array(3) {
["foo_foo"]=>
string(4) "foo2"
["bar_bar"]=>
string(4) "bar2"
["hoge_hoge"]=>
string(5) "hoge2"
}
[3]=>
array(3) {
["foo_foo"]=>
string(4) "foo3"
["bar_bar"]=>
string(4) "bar3"
["hoge_hoge"]=>
string(5) "hoge3"
}
[10]=>
array(3) {
["foo_foo"]=>
string(5) "foo10"
["bar_bar"]=>
string(5) "bar10"
["hoge_hoge"]=>
string(6) "hoge10"
}
[101]=>
array(3) {
["foo_foo"]=>
string(6) "foo101"
["bar_bar"]=>
string(6) "bar101"
["hoge_hoge"]=>
string(7) "hoge101"
}
}
*/
これで良さげ
ちなみに正規表現の'\w'は注意がいるみたい
正規表現「\w」の説明の訂正(レシピ045)
http://php-recipe.com/?p=483