こんにちは。PyQチームのtsutomuです。
正規表現の基礎に関連する話題を紹介します。
質問
正規表現の
Yes, I am.
とNo I am not.
を別々に取得したいのですが、Yes, I am." and "No I am not.
と抜き出した文字列が繋がってしまいます。どうすれば個別に取得できますか?
書いたコード
content = 'You say, "Yes, I am." and "No I am not.".' m = re.search('"(.*)"', content)
実行結果
Yes, I am." and "No I am not.
回答(正規表現のマッチの仕方)
上記の場合、 ダブルクォーテーションで囲まれた部分を探すので、 m.group(1)
はYes, I am." and "No I am not.
になります。 途中にダブルクォーテーションがあっても、最後のダブルクォーテーションの手前までマッチします。
解説
上記で、Yes, I am.
とNo I am not.
を別々に取得したい場合、2通りの方法があります。
- ダブルクォーテーションで囲まれた「ダブルクォーテーション以外の文字列」を探す方法
- ダブルクォーテーションで囲まれた最小の文字列を探す方法
それぞれ下記のように記述します。
※group(1)
がYes, I am.
、group(2)
がNo I am not
になります。
【1の場合】
m = re.search('"([^"]*)"[^"]*"([^"]*)"', content)
[^"]*
がダブルクォーテーション以外の並びを表します。
したがって、"([^"]*)"
が、「ダブルクォーテーションで囲まれたダブルクォーテーション以外の文字列」です。
【2の場合】
m = re.search('"(.*?)"[^"]*"(.*?)"', content)
.*?
が最小マッチを表し、なるべく短くマッチングします。
したがって、"(.*?)"
がダブルクォーテーションで囲まれた最小の文字列です。
また、re.findall()
を使うと全てのパターンを列挙してリスト化するので、次のように書くこともできます。
result = re.findall('"([^"]*)"', content) # ['Yes, I am.', 'No I am not.'] result = re.findall('"(.*?)"', content) # ['Yes, I am.', 'No I am not.']
このお悩み解決に関連するクエスト
このお悩み解決はPyQのクエストの補足情報として作成しています。PyQユーザーで興味がある方は「正規表現の基礎の2問目」をぜひ解いてみてください。