Python学習チャンネル by PyQ

Pythonのオンライン学習プラットフォームPyQのオフィシャルブログです

正規表現でダブルクォーテーションの間だけ取得するには?

f:id:kenken0326:20200910122145p:plain

こんにちは。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通りの方法があります。

  1. ダブルクォーテーションで囲まれた「ダブルクォーテーション以外の文字列」を探す方法
  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問目」をぜひ解いてみてください。

関連記事

正規表現「[^、]、([^、])、(\d+)円$」の意味と、メソッド groupの解説

blog.pyq.jp

正規表現の先頭につくrの意味、エスケープシーケンスやrow文字列の解説

blog.pyq.jp

Copyright ©2017- BeProud Inc. All rights reserved.