本サイトではアフィリエイト広告を利用しています
アクセント記号などの特殊文字をPHPの正規表現でマッチ

コード 正規表現

アクセント記号などの特殊文字をPHPの正規表現でマッチさせる

2020年11月9日

正規表現にはいろいろと苦労させられます。
ここ最近の経験で難儀した例を共有したいと思います。
私もよく使う preg_match 関数ですが、「ハンドル名(:IDコード)」(文字列はアルファベット)といった形式の文字列を探していた時に、Mozilla 系のブラウザで頻繁に問題が発生しました。
ゲームのアカウント名などによく使われる文字「à、î、ë、é、ü など」のアキュート・アクセントを付した文字(国際文字)をうまく拾ってくれませんでした。

真っ先に書いた正規表現コードは「A-z」を「ハンドル名」のマッチ検索に使用しました。勝手に「A-z」はアクセントを付した文字(国際文字)にも一致すると想定していましたが、実際は全くそうはならないことがすぐにわかりました。

 

preg_match(
  "/([A-Za-z -]+)?\s?\[?\(?:([A-Za-z0-9\-\_]+)\)?\]?/",
  "Pokémon [:pokemon]", $matches);
// 0 => 'Pokémon [:pokemon123]', 1 => 'Pokémon', 2 => 'pokemon123'

上のようなコードは、誰でも思いつきで書けて、しかも普通に想定する一般的文字列には完ぺきに機能します。だから、一度うまく動くとこれで問題ないと過信してしまいがちです。

ゲームユーザーに多いのですが、「Pokémon GO」のようなよく知られた商標から、上手くモジってハンドル名をつける人によく出くわします。

国際文字にマッチさせるには、2か所ばかり正規表現を書き換えてやる必要がありました。

  • マッチさせたい部分で「A-z」とやっていた箇所を「\pL」と書き換えます。
  • u 修飾子を追加して、文字列を UTF-8 として扱われるようにします。

PHP 5.1.0 以降、UTF-8 モードを使う場合は、「\pL」はアルファベットの大文字・小文字、擬似文字を含む国際文字にマッチします。

書き換えた上の正規表現は次のような感じになります

 

preg_match(
  "/([\pL -]+)?\s?\[?\(?:([\pL0-9\-\_]+)\)?\]?/u",
  "Pokémon [:pokemon]", $matches);
// 0 => 'Pokémon [:pokemon]', 1 => 'Pokémon', 2 => 'pokemon'

単純な方法ですが、知っていると便利なこともありますので、活用する機会があったら使ってみてください。

-コード, 正規表現
-, ,