正規表現で任意の文字を取得したい ~先読みと後読み~


はじめに

先日、正規表現を使用した面白い依頼をいただいたので備忘録として

題名の通り、先読み後読みというものを使用して、間の文字を取得してみた

「そもそも正規表現ってなんぞや」「メタキャラクタとか忘れた!」
「メールアドレスとURLの正規表現も知りたいな」
 …という方は以前投稿した[こちら][1]を参考にしていただけたら光栄です!

今回のお品書きはこちら

  • 今回の依頼内容
  • 先読み、後読みとは
  • 使用例

今回の依頼内容

今回、こんな依頼を受けた

「正規表現で文字列にある任意の文字を取得したい」

例えば、
test_123から123を取得したい
get12sampleget150sampleから12150を取得したい
s0mplestr32@tests1mpletrs43@123aからstr32trs43を取得したい

一つ目は正規表現じゃなくてもできそうだけど、二つ目以降は正規表現でも難しそうだ…
ということで、いろいろ調べてみたところ、先読み後読みというものに出会った

先読み、後読みとは

先読み ... 先読み表明(lookahead assertion)
後読み ... 後読み表明(lookbehind assertion)

先読み表明 (?=XXX)

名前からしてXXXから始まる文字列 XXX123 と考えてしまうが、逆 123XXX である

要するに、「後にXXXがある文字列を取得」という正規表現である
123XXX の場合、正規表現を123(?=XXX)や.+(?=XXX)とすれば 123 を取得できる

否定「後にXXXがない文字列を取得」にしたい場合は.+(?!XXX)と記載する

後読み表明 (?<=YYY)

先読み表明の反対なので、「前にYYYがある文字列を取得」という正規表現である
YYY123 の場合、正規表現を(?<=YYY)123や(?<=YYY).+とすれば 123 を取得する

否定「前にYYYがない文字列を取得」にしたい場合は(?<!YYY).+と記載する

使用例

今回の依頼内容で記載した例を使用します

test_123 から 123 を取得

test_123の特徴

  • 前にtest_がある文字列(123)をする(後読み表明)

上記の特徴を踏まえて、作成した結果がこちら

(?<=test_)123

上記のサンプルがあるため、説明は必要ないかと思います

get12sample や get150sample から 12 や 150 を取得

get12sample と get150sampleの特徴

  • 前にgetがある文字列を取得する(後読み表明)
  • 後にsampleがある文字列を取得する(前読み表明)
  • 間の数字が可変である

上記の特徴を踏まえて、作成した結果がこちら

(?<=get)\d+(?=sample)

部分ごとに見ていきましょう

(?<=get)

後読み表明の記法

\d+

数字を一回以上繰り返す記法

\d{1,} でも代用可能
数字が2,3桁固定なのであれば、\d{2,3} が良いかと

(?=sample)

先読み表明の記法

以上より、所望の正規表現ができました!

s0mplestr32@test や s1mpletrs43@123a から str32 や trs43 を取得したい

s0mplestr32@1test と s1mpletrs43@testの特徴

  • 取得したい文字列の前にはs[一桁数字]mpleがある
  • 前にs[一桁数字]mpleがある文字列を取得する(後読み表明)
  • 後に@​1testまたは@​testがある文字列を取得する(前読み表明)
  • 間には英字三文字、数字二文字かあり、可変である

上記の特徴を踏まえて、作成した結果がこちら

(?<=s(\d)mple)[a-z]{3}\d{2}(?=@(1?)test)

部分ごとに見ていきましょう

s(\d)mple

\d は数値
()がなくても動くが、()がないと一目で分かりづらいため、つけてある
\d{1} としても問題ないが \d は数字一文字という意味なのでなくてよい

(?<=s(\d)mple)

後読み表明の記法

[a-z]{3}\d{2}

[a-z]{3} で数字以外三文字
\d{2} で数字二文字

今回の文字は小文字英字しか対応していないため、条件によって[A-Za-z]\Dに変更してください

@(1?)test

1? は1が0回または1回表示したものという意味
()がなくても動くが、()がないと一目で分かりづらいため、つけてある
1の部分が任意の数値や英数字の場合は \d\w に変更してください

(?=@(1?)test)

先読み表明の記法

以上より、所望の正規表現ができました!

さいごに

前回の記事であらかた理解していたつもりでしたが、まだまだ正規表現は奥が深かった

今までリスト化して分解したりしていましたが、正規表現を使いこなせばそんなことしなくてもいいですね!

今回の先読みと後読みを調べていくうちに他にも面白そうな正規表現があったので余裕があれば再度記事作成していきたいと思います(^ω^ )

[1]:https://qiita.com/str32/items/a692073af32757618042