「住所録のExcelファイルがある。郵便番号にハイフンが入っているので取ってくれる?」
こんな話は、どこのオフィスでもありそうですね。Excelにあるデータなら置換機能で対応できます。
ではこんなケースはどうでしょうか?
住所録のソフトから住所をCSV出力した。郵便番号・都道府県・市区町村・住所詳細の順で並んでいる。
こいつを別のソフトに取り込みたいけど、郵便番号のハイフンが原因で取り込めないんだよ。ハイフンを取ってくれる?
Excelに取り込んでから置換機能で対応できます。
しかしExcelに取り込むときに住所詳細の1-11が勝手にJan-11に変換されて、それに気づかなかったり・・・となると収拾がつかないですよね。
なんとか、数値3桁+数値4桁だけで取り出せないだろうか?そう思うのが自然です。
そんなときに役立つのが正規表現です!
本記事では、正規表現について解説します。
正規表現はそれだけで本が出せるほど奥深いものです。詳細は他のサイトや良書を読んでいただくとして、ここでは「やることベース」で攻めていきます。
正規表現とは何か
正規表現とは、調べたいパターンを、メタ文字で表現したものです。プログラミングの中だけではなく、一般的な技法です。
どのテキストエディタにも備わっている機能です。秀丸をはじめとして、sakuraエディタ、Sublime Text、me、開発ツールではEclipseやBlacketsにも搭載されています。
もちろん、プログラム中でも使えます。
例えばユーザーに入力させた郵便番号が3桁ハイフン4桁の数字かどうか、メールアドレスが正しい形式か、などを判断させて、形式にそぐわないならエラーを表示、といった使い方です。
メタ文字
正規表現に限らず「メタ」という言葉は、何かを超越したものという意味で使われることが多いです。
つまりこの場合、メタ文字とは文字としての意味以上の意味を持つもの、ということができます。
メタ文字とは、以下の種類があります(Rubyマニュアルより抜粋)。
これらを使って見つけたいパターンを表現したものが正規表現、ということです。
郵便番号を正規表現で検索
先ほどから出ている例「郵便番号」を検索してみましょう。
3桁ハイフン4桁なら、これで大丈夫です。
¥d¥d¥d-¥d¥d¥d¥d (Windows) \d\d\d-\d\d\d\d (Mac)
お手持ちのテキストエディタで構いませんが、本記事ではMacで解説します。
エディタを開き、まずは以下の文字列をコピペしてください。
123-4567 098-7654 1234567 a123456 1234-567
そして、文字列検索(このあたりはお手持ちのエディタ名+正規表現などでググって調べてください)にて、先の正規表現を入力してください。以下はSublime Textの例です。
検索してみてください。
最初の2つだけヒットしたのがわかります。
指定した正規表現にマッチするもの以外は無視されたのです。
これだけでもなんとなく正規表現のイメージがつかめたのではないでしょうか?
郵便番号でないものを正規表現で検索
ご無体な上司がさらに続けます。
桁数的に郵便番号になっていないものもあるんだよね。調べてくれる?
桁数的??
ということは、3桁ハイフン4桁になっていないということですね。
先の例ではマッチするものを調べましたが、今度はマッチしないものを調べましょう。
繰り返し、否定の正規表現
パターンを繰り返す正規表現もあります。
\d{3}-\d{4}
これで郵便番号の形式のものを判定できます。
\dは数字1文字を表します。{回数}は回数分繰り返すもの、という意味になります。
3桁4桁で、かつハイフンで繋がれたものということで、郵便番号の書式を表すわけです。
桁数を固定しましたが、n桁からm桁までという指定は{n,m}となります。
否定先読み
では、3桁ハイフン4桁ではないという正規表現を、以下に示します。
^(?!\d{3}-\d{4}).*$
これでもう一度以下を検索してください。
123-4567 098-7654 1234567 a123456 1234-567
結果はこうなります。
上から2つは問題ない郵便番号なのでマッチしませんでした。
ところがその下3つはマッチしました。形式に沿っていないからです。
ここは難しいのでじっくり解説しましょう。
先の正規表現^(?!\d{3}-\d{4}).*$の中で、(?! )は文字列を検索しているわけではありません。
否定先読みという手法で、位置を検索しています。
もっと簡単な例でいきましょう。
a(!?\d)
これで何がマッチするか見てください。a1がマッチするはずです。
aから見て後ろが数字以外の1文字のものを探す、と解釈できますね。
また、^は行頭、.は任意の一文字、*は0回以上の繰り返し(要は繰り返ししないのもOK)となります。
まとめるとこうなります。
^(?!\d{3}-\d{4}).*$
- 先頭から見る
- 先頭が数値3桁-数値4桁以外
- 上記以降、任意の文字が続く
これで正しい形式の郵便番号以外がマッチしたというわけです。
やっとご無体な上司の要望を満たすことができました。
Rubyでは正規表現をどうするか
Rubyでは、正規表現は=~を使います。
str = '123-4567' if /\d{3}-\d{4}/ =~ str puts 'マッチしました' else puts 'マッチしません' end
strの中身に、上記の「否定先読み」で出てきた郵便番号の書式ではないものや、「1234567」や「a123456」を入れて試してください。
マッチしません、と表示されるはずです。
正規表現をもっと試したい方に
正規表現をもっと書きたい!試したい!という方にアドバイスです。
エディターを使うのも良いですが、正規表現を手軽に試せるサイトはたくさんあります!
「正規表現 試す」でググってください。正規表現チェッカーなどのサイトがヒットします。
それらのサイトでは、正規表現と試したい文字列を入力する欄があり、マッチするかどうかが簡単に試せます。
また、自分が書いた正規表現をさらに理解を深めるには、部分的に表現を削ったり変えたりすると結果がどう変わるかを見るというのも有効です。
まとめ
正規表現の雰囲気は感じることができたでしょうか?
奥の深い正規表現のほんの一部しか触れていません。ぜひご自身でいろいろと書いてみて、理解を深めてくださいね!