3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

オーバーラップあり正規表現 in Python and Java

Posted at

参考:
https://stackoverflow.com/questions/17971466/java-regex-overlapping-matches

ふつう正規表現のmatchを取るときは、あるマッチで採択された文字列部分は、他のマッチで重複して利用されない。
例えば「 _apple_banana_cherry_ 」という文字列から、
/_[^_]+_/をマッチさせると取れるのは _apple__cherry_ の2つ。
オーバーラップする"_"を利用して _apple_, _banana_, _cherry_ の3つを取りたい場合は特殊な指定が必要になる。

pythonの場合

簡単な方法は、正規表現パッケージの regex を使い、オプション overlapped=True でマッチさせる。

{.python}
>>> import regex as re
>>> re.findall("_[^_]+_", "_apple_banana_cherry_")
['_apple_', '_cherry_']
>>> re.findall("_[^_]+_", "_apple_banana_cherry_", overlapped=True)
['_apple_', '_banana_', '_cherry_']

Javaの場合

Javaの場合は標準の正規表現パッケージを利用し、startIndexをずらしていく方法をとるのが簡単。

{.java}
Matcher m = Pattern.compile("_[^_]+(_)").matcher("_apple_banana_cherry_");
if (m.find()) {
    do {
        System.out.println(m.group());
    } while (m.find(m.start(1)));
}

解説:
/_[^_]+(_)/ で、2番目に出現する _()で括ってグループ1として取得できるようにしている。
m.start(1)は、グループ1の先頭インデックスを返す。
m.find(N)はN番目の文字からマッチを開始するという意味。
なので m.find(m.start(1))は、m.find()をグループ1の先頭インデックスから開始するという意味になり、
つまり2回目以降のループでは、マッチした文字列の末尾の _ から次のマッチを開始するというループになっている。

note:
どのグループを次回マッチの先頭インデックスとするかの指定は、名前付きグループを使ったほうがわかりやすいかもしれない。

{.example}
(?<name>PATTERN)

また、より複雑なマッチパターンの場合は非キャプチャグループが必要になるかも。

{.example}
(?:PATTERN)
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?