6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【PHP】正規表現で都道府県を取り除く

Posted at

やりたいこと

PHPで正規表現を用いて、住所から{都道府県}の部分を取り除き、{市区町村}以下を抽出したい。
具体的には、preg_replace()関数を用いて、{都道府県}部分を空文字列''に置換することで取り除く。

$address = '東京都港区芝公園4丁目2-8';
echo preg_replace(正規表現パターン, '', $address);
// 港区芝公園4丁目2-8

やったこと

正解にたどり着くまでの経緯を、ダメだったパターンを交えて記す。
(本記事では正規表現パターンの詳しい説明は割愛します)

ダメなパターン1

正規表現パターン:/.*(都|道|府|県)/
(任意の文字を0回以上 + 都・道・府・県のいずれか にマッチ)

sample1
$address = '東京都港区芝公園4丁目2-8';
echo preg_replace('/.*(都|道|府|県)/', '', $address);
// 港区芝公園4丁目2-8 (正しい!)
sample2
$address = '栃木県宇都宮市旭1丁目1-5';
echo preg_replace('/.*(都|道|府|県)/', '', $address);
// 宮市旭1丁目1-5 (おかしい!)

sample1では、東京都の部分がうまくマッチして置換できているが、
sample2では、宇都宮市の「都」までをパターンとしてしまい、「宮市旭1丁目1-5」となってしまっているので誤り。

ダメなパターン2

正規表現パターン:/^.{2,3}(都|道|府|県)/
(先頭に任意の文字が2~3回 + 都・道・府・県のいずれか にマッチ)

sample3
$address = '東京都港区芝公園4丁目2-8';
echo preg_replace('/^.{2,3}(都|道|府|県)/', '', $address);
// 東京都港区芝公園4丁目2-8 (おかしい!)

sample3では、東京都の部分が取り除かれると思いきや、元の文字列と同じ文字列が返されてしまった。

調べてみたところ、日本語はマルチバイト文字なので、{2,3}の部分でバイト数がうまく機能していないことが判明した。
この場合、パターン修飾子「u」をつけて、対象文字列がUTF-8エンコードされていることを明示するか、
文字数指定の部分を3バイト換算({6,9})で書き換える必要がある。

sample4
$address1 = '東京都港区芝公園4丁目2-8';
echo preg_replace('/^.{2,3}(都|道|府|県)/u', '', $address1);
// 港区芝公園4丁目2-8 (正しい!)
echo preg_replace('/^.{6,9}(都|道|府|県)/', '', $address1);
// 港区芝公園4丁目2-8 (正しい!)

$address2 = '栃木県宇都宮市旭1丁目1-5';
echo preg_replace('/^.{2,3}(都|道|府|県)/u', '', $address2);
// 宇都宮市旭1丁目1-5 (正しい!)
echo preg_replace('/^.{6,9}(都|道|府|県)/', '', $address2);
// 宇都宮市旭1丁目1-5 (正しい!)
sample5
$address = '東京都府中市日吉町1−1';
echo preg_replace('/^.{2,3}(都|道|府|県)/u', '', $address);
// 中市日吉町1−1 (おかしい!)

sample4では、日本語のバイト数問題を解決して正しく置換できた。
しかし、sample5のような住所だと、「東京都」ではなく「東京都府」の部分までマッチしてしまっているので誤り。

成功パターン

上の2つの間違ったパターンを経て、以下のような結論に落ち着いた。

正規表現パターン:/(東京都|北海道|大阪府|京都府|^.{2,3}県)/u
(東京都 or 北海道 or 大阪府 or 京都府 or 先頭に任意の文字が2~3回 + 県にマッチ)

sample6
$address1 = '東京都港区芝公園4丁目2-8';
echo preg_replace('/(東京都|北海道|大阪府|京都府|^.{2,3}県)/u', '', $address1);
// 港区芝公園4丁目2-8 (正しい!)

$address2 = '栃木県宇都宮市旭1丁目1-5';
echo preg_replace('/(東京都|北海道|大阪府|京都府|^.{2,3}県)/u', '', $address2);
// 宇都宮市旭1丁目1-5 (正しい!)

$address3 = '東京都府中市日吉町1−1';
echo preg_replace('/(東京都|北海道|大阪府|京都府|^.{2,3}県)/u', '', $address3);
// 府中市日吉町1−1 (正しい!)

$address4 = '岐阜県山県市高木1000-1';
echo preg_replace('/(東京都|北海道|大阪府|京都府|^.{2,3}県)/u', '', $address4);
// 山県市高木1000-1 (正しい!)

東京都, 北海道, 大阪府, 京都府は完全一致でマッチさせ、
先頭にきた〇〇県または〇〇〇県をマッチさせることで、
正しく都道府県部分を取り除くことができた。

おわりに

正規表現は奥が深い......

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?