89750


### 行いたいこと

ある単語（スペースや記号を含んで２単語以上もあり得る）が、対象文に含まれるかどうかを判定する

## 現在のコードと課題

現在のコードでは、対象文2、4のみ想定通りの出力となリます。

末尾にピリオドがあったり、前と後ろの両方にスペースがある場合は、どのように正規表現を定義するべきですか。

[code]

    import regex as re
    words = ['are', 'John Smith', 'Mia & Tim']
    re_words = "(" + "|".join(words) + "|" + ")"
    target_1 = "I am John Smith."
    target_2 = "Mia & Tim look fine"
    target_3 = "There are Mia & Tim & Kate."
    target_4 = "are you sure?"
    
    print(re_words)
    print(re.match(re_words, target_1)) #「John Smith」は含まれている
    print(re.match(re_words, target_2))
    print(re.match(re_words, target_3)) #「Mia & Tim」は含まれている
    print(re.match(re_words, target_4))
    
    
    #output
    (are|John Smith|Mia & Tim|)
    <regex.Match object; span=(0, 0), match=''>
    <regex.Match object; span=(0, 9), match='Mia & Tim'>
    <regex.Match object; span=(0, 0), match=''>
    <regex.Match object; span=(0, 3), match='are'>
    
[/code]

## 試したこと

`re.search`と以下のように変更してみましたが、結果に変更ありませんでした。

[code]

    import re
    words = ['are', 'John Smith', 'Mia & Tim']
    re_words = "(" + "|".join(words) + "|" + ")"
    target_1 = "I am John Smith ."
    target_2 = "Mia & Tim look fine"
    target_3 = "There are Mia & Tim & Kate."
    target_4 = "are you sure?"
    
    print(re_words)
    print(re.search(re_words, target_1))
    print(re.search(re_words, target_2))
    print(re.search(re_words, target_3))
    print(re.search(re_words, target_4))
    
    
    #output
    (are|John Smith|Mia & Tim|)
    <re.Match object; span=(0, 0), match=''>
    <re.Match object; span=(0, 9), match='Mia & Tim'>
    <re.Match object; span=(0, 0), match=''>
    <re.Match object; span=(0, 3), match='are'>
    
[/code]

## 試したこと２

正規表現を修正したのですが、部分一致になると、以下の例でもマッチしてしまい、あくまでもスペース含む独立した単語でマッチしたいのでエラーケースを引き起こすことがわかりました。

[code]

    import re
    words = ['are', 'John Smith', 'Mia & Tim']
    re_words = "(" + "| ".join(words) + ")"
    target_4 = "areyou sure?"
    
    print(re_words)
    print(re.search(re_words, target_4))
    
    
[/code]


CC BY-SA 4.0
2022-07-04T00:16:34.387
89747
2022-07-04T06:39:29.377
2022-07-04T05:47:08.987
question
python3 正規表現
正規表現を変更して求める出力を得たい


[`re.match`](https://docs.python.org/ja/3/library/re.html#re.match)は
**文字列の先頭が一致する** 場合に値を返します。  
部分一致で正規表現検索をかけたい場合は[`re.search`](https://docs.python.org/ja/3/library/re.html#re.search)を使用してください。

参考資料:

  * [search() vs. match()](https://docs.python.org/ja/3/library/re.html#search-vs-match)
  * [【python】re.match より re.search を使おう](https://qiita.com/halhorn/items/9e6599a3422e7dd94ec8)

追記:  
要望に合致するサンプルコードを作成しました。  
連続する単語が前後にないことを確認する場合は、コメント回答にある`\b`(単語境界)を使用してください。

**サンプルコード**

[code]

    import re
    words = ['are', 'John Smith', 'Mia & Tim']
    
    # 単語境界を使用する例
    re_words = rf"\b({'|'.join(words)})\b"
    
    # その他に、 \W(非単語文字)と ^(文頭)、 $(文末)を組み合わせて実現できなくもない
    # re_words = r"(?:^|\W)(" + "|".join(words) + ")(?:\W|$)"
    
    targets = {
        # "文章": "想定結果"
        "I am John Smith.": "John Smith",
        "I am John Smithhhhhhhhh.": None,
        "Mia & Tim look fine": "Mia & Tim",
        "There are Mia & Tim & Kate.": "are",
        "are you sure?": "are",
        "areyou sure?": None,
        "There are Mia & Tim & Kate.": "Mia & Tim", # 想定結果が間違っている例
    }
    
    print(re_words)
    
    for target in targets.keys():
        wanted = targets[target]
        m = re.search(re_words, target)
        # 例文が想定結果になっているかチェックするアサーション(想定結果と異なる場合は例外となる)
        try:
            assert (wanted == None and m == None) or (wanted == m[1]), '文章: {0}, 想定結果: {1}", 実行結果: {2}'.format(target, wanted, m)
        except Exception as e:
            print(e)
    
[/code]


CC BY-SA 4.0
2022-07-04T01:56:20.297
89750
2022-07-04T06:39:29.377
2022-07-04T06:39:29.377
9820
9820
89747
answer