環境
- windows10
- PHP 8.x
- VsCode
- gitbash 2.32.0.1
やりたいこと
以下のようなフレームワーク(プログラム言語)の配列から()の中に含まれるプログラム言語名だけの配列に変換したい
なお、()は半角・全角混合しているので、半角に統一すること
// 完成形 [ PHP, Ruby, Java, Python ];
$languagesStr = "Laravel(PHP)、Rails(Ruby)、Spring(Java)、Django(Python)";
使用する置換処理・正規表現関連のメソッド
- str_replace
検索文字列に一致したすべての文字列を置換する - explode
ある文字列をもとに特定の文字列を配列に分割する - preg_match
正規表現によるマッチングを行う
正規表現
実装内容
実装の順番は以下の通り
- str_replaceにより、()をすべて半角に統一する
- explodeにより、”、”区切りで配列に変換
- ()の中身<プログラム言語名>のみをpreg_matchの正規表現で取り出す
<?php
// 完成形 [ PHP, Ruby, Java, Python ];
$languagesStr = "Laravel(PHP)、Rails(Ruby)、Spring(Java)、Django(Python)";
// 1.()をすべて半角に統一する
$replace_rule = [
"(" => "(",
")" => ")",
];
$replacedLanguagesStr = str_replace(array_keys($replace_rule), array_values($replace_rule), $languagesStr);
// 2."、"区切りで配列に変換
$replacedLanguagesList = explode("、", $replacedLanguagesStr);
// 3.()の中身<プログラム言語名>のみを正規表現で取り出す
$regex = function ($replacedLanguage) {
// (hoge)のパターン
if (preg_match("/(?<=\().+?(?=\))/", $replacedLanguage, $matches)) {
return $matches;
}
// hoge)パターン
if (preg_match("/.+?(?=\))/", $replacedLanguage, $matches)) {
return $matches;
}
// (hogeのパターン
if (preg_match("/(?<=\().+/", $replacedLanguage, $matches)) {
return $matches;
}
return $replacedLanguage;
};
$regexedLanguagesList = array_map($regex, $replacedLanguagesList);
var_dump($regexedLanguagesList);
?>
array(4) {
[0]=>
array(1) {
[0]=>
string(3) "PHP"
}
[1]=>
array(1) {
[0]=>
string(4) "Ruby"
}
[2]=>
array(1) {
[0]=>
string(4) "Java"
}
[3]=>
array(1) {
[0]=>
string(6) "Python"
}
}
補足
エスケープについて
/を使用してエスケープする必要のある文字列が複数存在する。例えば、.+(?=)) などは”)”で終わる文字列をマッチさせる場合に使用するが、”)”をそのまま使用すると正規表現上での意味合いとして認識されるため、/を使用してエスケープしてあげる必要がある(特殊文字を文字として認識させる)
正規表現一覧
正規表現 | 内容 | 使用例 |
\d | 半角数字1文字 | fefjeijfei3dfeo 9fjfijiekas3kjfie6 |
[a-z] | aからzまでのアルファベット [0-9]とすると0~9の数字 | 934f z9993d |
{n} | 直前の文字がn文字 | [0-9]{4}とすると、以下のようにマッチ jfead4432f |
? | 直前の文字またはパターンの0回、または1回の繰り返し | Laravel? とすると、 LaravelFramework でも LaraveFramework でもマッチする(?の直前はなくてもよいので) |
+ | 直前の文字が 1 回以上連続する文字にマッチ | [1-9]+とすると、 11444443325646f |
. | 任意の文字1文字 | [1-9].とすると 1kw |
* | 直前の文字が0個以上 | Laravel* とすると、 ?と同じで?の直前はなくてもいいので、 LaraveFramework でもマッチ ただし、?と違って連続でもマッチするので、 LaravellllllllllllllllllllllllllllllllllFramework としてもマッチする |
\s | 垂直タブ以外のすべての空白文字にマッチ | Laravel Rails Spring 上記だと、各フレームワーク名の間の空白文字にマッチする |
(?=hoge) | 直前に指定した文字列がある場合にマッチする(先読み) 後ろの文字を参照する | 例えば、.+(?=@) とすると、 @より前の文字がマッチする laravel@co.jp |
(?<=hoge) | 直後に指定した文字列がある場合にマッチする(後読み) <があると後読みなので、前の文字を参照すると覚えればよい。 | .+(?=hoge) dkdkhogefee |
先読み・後読みを使うことで、例えば、以下のようなurlからid部分を取り出すということも簡単に可能です。
- https://drive.google.com/open?id=1eITjBGZ45G5D94kB4IStl5T7qawikbRT
- https://drive.google.com/open?id=1tgfyzY3b7FevxyBG2oIpHpizvoGTgMBU
$filePreviewUrlList = [
"https://drive.google.com/open?id=1eITjBGZ45G5D94kB4IStl5T7qawikbRT",
"https://drive.google.com/open?id=1tgfyzY3b7FevxyBG2oIpHpizvoGTgMBU"
];
foreach ($filePreviewUrlList as $url) {
preg_match('/(?<=id=).+/', $url, $matches);
var_dump($matches);
}
array(1) {
[0]=>
string(33) "1eITjBGZ45G5D94kB4IStl5T7qawikbRT"
}
array(1) {
[0]=>
string(33) "1tgfyzY3b7FevxyBG2oIpHpizvoGTgMBU"
}
なお、今回の実装では、hoge(foo) のfooの部分だけ取れればよいので、以下のように後読みと先読みを合体させて、()の中に含まれる任意の文字の1回以上の連続にマッチさせています
(?<=\().+(?=\))
正規表現が試せるサイト
正規表現を試す際には、以下サイトがおすすめなので、ぜひ活用してみてください。

regex101: build, test, and debug regex
Regular expression tester with syntax highlighting, explanation, cheat sheet for PHP/PCRE, Python, GO, JavaScript, Java, C#/.NET.
コメント