住所の分割 都道府県/市区町村/町名
住所を正規表現で都道府県、市区町村、町名に分割
PHP
preg_match('/(東京都|北海道|(?:京都|大阪)府|.{6,9}県)((?:四日市|廿日市|野々市|臼杵|かすみがうら|つくばみらい|いちき串木野)市|(?:杵島郡大町|余市郡余市|高市郡高取)町|.{3,12}市.{3,12}区|.{3,9}区|.{3,15}市(?=.*市)|.{3,15}市|.{6,27}町(?=.*町)|.{6,27}町|.{9,24}村(?=.*村)|.{9,24}村)(.*)/', $str, $matches);
UTF8
文字コードがUTF8のため.{2,3}県ではなく、.{6,9}県。
連続した文字列の対応
○○市△△市、○○町△△町などの連続して同じ文字列が含まれるものを先読み(.{3,15}市(?=.*市))で抽出。2回目の同じ文字列が終端にならないようにする。
これにマッチしない四日市市、廿日市市、野々市市、杵島郡大町町を先行処理。
Array
(
[0] => 千葉県市川市市川
[1] => 千葉県
[2] => 市川市
[3] => 市川
)
Array
(
[0] => 三重県四日市市相生町
[1] => 三重県
[2] => 四日市市
[3] => 相生町
)
政令指定都市以外の○○市△△区
臼杵を○○市△△区より先行処理。
この組み合わせが他にも多数あるのであれば、.{3,12}市.{3,12}区を(?:札幌|仙台|さいたま|千葉|横浜|川崎|相模原|新潟|静岡|浜松|名古屋|京都|大阪|堺|神戸|岡山|広島|北九州|福岡|熊本)市.{3,12}区にすべき。
Array
(
[0] => 大分県臼杵市市浜千代田区
[1] => 大分県
[2] => 臼杵市
[3] => 市浜千代田区
)
文字数範囲指定
町名に市・区・町・村が含まれているものがあるため、市・区・町・村に文字数制限(.{3,12}市.{3,12}区)を設定し、これを回避する。
市については、{3,18}市にすると、町名に含まれる市まで抽出してしまうので、{3,15}市に設定し、かすみがうら、つくばみらい、いちき串木野を先行処理。
(参考)
区(市部分):さいたま市(4字)-堺市(1字)
区(区部分):保土ヶ谷区(4字)-堺区(1字)
23区:江戸川区(3字)-港区(1字)
市:かすみがうら市(6字)、南アルプス市(5字)-津市(1字)
町:南都留郡富士河口湖町(9字)-大島町(2字)
村:北秋田郡上小阿仁村(8字)-新島村(2字)
Array
(
[0] => 茨城県かすみがうら市有河
[1] => 茨城県
[2] => かすみがうら市
[3] => 有河
)
市が含まれる町
町より市を先に処理しているため、市が含まれる余市郡余市町、高市郡高取町を市より先に処理。
Array
(
[0] => 北海道余市郡余市町朝日町
[1] => 北海道
[2] => 余市郡余市町
[3] => 朝日町
)
12万件の住所一覧で試したのですが、ほぼ分割できているのではないかと思います。もし、うまく分割できないところが見つかれば更新する予定です。