それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

正規表現で一番最後に出現したものを取得する

正規表現で最後に出てきたものを取りたい

たとえば、次のようなファイル名のファイルがあるとして、ここから、数字を取り出したい。

しかも欲しい数字は(2)の2が欲しい。

2016-08-07の売上報告のコピー(2).xls # 欲しい数字2、それも(2) の中の2が欲しい。

どうやるか。

通常であれば、数字にマッチさせ、マッチ個数を見て、最後を取り出せば、いいんだろうけど。

正規表現だけで実現できないかなと思いついたので調べみました。

正規表現で、最後にマッチしたものだけを取り出せないか、考えてみました。

考えた結果がコレ

/([\d]+)[^\d]+$/

実際の結果はこちら

'2016-08-07の売上報告のコピー(13).xls'.match /([\d]+)[^\d]+$/ #=> #<MatchData "13).xls" 1:"13">

ポイント

最初に、数字にマッチさせてみた。

>> '2016-08-07の売上報告のコピー(13).xls'.scan /([0-9]+)/
=> [["2016"], ["08"], ["07"], ["13"]]

数字にマッチさせてみると、それっぽいのが取れるんで。

つぎに、数字+数字以外+行末にマッチさせる。

>> '2016-08-07の売上報告のコピー(13).xls'.scan /([\d]+)[^\d]*$/
=> [["13"]]

これでいける。つまり、ココから言えることは、

最後の出現を取りたいときは、欲しい文字+欲しい文字以外+末尾とすればいいとわかる。

最後の出現=(欲しい文字+欲しい文字以外)の組み合わせ。

英単語(小文字)で一番最後に出現したものを取る場合

>> 'iPhone は iOS を使った Apple の製品です。'.scan /([A-Za-z]+)[^A-Za-z]*$/
=> [["Apple"]]

N番目の出現は、流石にしんどいけど、何個か組み合わせば、実現できそう

最後から二つ目を取るには

>> 'iPhone は iOS を使った Apple の製品です。'.scan /([A-Za-z]+)[^A-Za-z]*[A-Za-z]*[^A-Za-z]*$/
=> [["iOS"]]
>>

正規表現(欲しい文字)+欲しい文字以+外欲しい文字+欲しい文字以外 と組み合わせで実現できそうですね。

先頭から2番めに出てきた数字列にマッチさせる。

この方法を考えていけば、先頭から2回めに出てきた文字列にマッチさせることが出来ると思いました。

>> '2016-08-07の売上報告のコピー(13).xls'.scan /^[^\d]*[\d]+[^\d]*([\d]+)/
=> [["08"]]
>> '2016-08-07の売上報告のコピー(13).xls'.scan /^[^\d]*[\d]+[^\d]*[\d]+[^\d]*([\d]+)/
=> [["07"]]

あとはコレを複数個組み合わせれば、先頭からN番目も一回の正規表現で取り出せそうですね。

まぁ実際には、マッチ配列から取出すことのほうが多いんですけど。