以下のようにタグで囲まれた文字からタグを取り出そうとすると、先頭の'<‘と最後尾の’>’に対して文字列全体がマッチしてしまう。
1 2 3 4 |
str = '<> < > <abc> <123>' print(re.findall('<.*>', str)) # ['<> < > <abc> <123>'] |
これは正規表現のマッチングができるだけ長い文字列でヒットさせようとする貪欲な(greedy)マッチングのため。
これを非貪欲(non-greeding)なマッチングにするためには*
→*?
とする。この場合、できるだけ短くマッチするようになり、個々のタグが分解される。
1 2 3 |
print(re.findall('<.*?>', str)) # ['<>', '< >', '<abc>', '<123>'] |
タグの間に1文字以上入っていることを意図して以下のようにしても、やはり貪欲にマッチする。
1 2 3 |
print(re.findall('<.+>', str)) # ['<> < > <abc> <123>'] |
これを非貪欲にマッチさせようとすると、以下のように最初のタグのの'>'
ではなく、その次の'>'
にマッチする。最初のタグの'<'
に対して、その後複数の文字を経て到達するのが2つ目のタグの'>'
のため。
1 2 3 |
print(re.findall('<.+?>', str)) # ['<> < >', '<abc>', '<123>'] |
以下のように、意図する文字構成をできるだけ詳しく記述する方がよい。
1 2 3 |
print(re.findall('<\w+>', str)) # ['<abc>', '<123>'] |