

正規表現で特定文字列より前にマッチさせたいのですが、  
その特定文字列が含まれない場合には、元の文字列にマッチさせるようにするには  
どうすればよいでしょうか。

抽出したい内容：  
"aaa"または"bbb"が対象に含まれる場合には、その前までの文字列、  
含まれない場合には元の文字列、にマッチさせたいです。

やってみた正規表現：

[code]

    "(.*?)(aaa|bbb).*"
    
[/code]

これだと"aaa"または"bbb"を含む場合にはその前の文字列にマッチしますが、  
"aaa"や"bbb"にもマッチしてしまうのと、  
"aaa"や"bbb"を含まない場合には何にもマッチしません。


CC BY-SA 4.0
2020-02-22T10:23:04.253
63276
2020-02-23T06:48:39.057
2020-02-23T06:48:39.057
2376
37726
question
python 正規表現
正規表現でマッチしない場合には元の文字列にマッチさせたい


**回答**  
`re.sub`で終了文字列パターン以降を空文字列に置換したものが抽出結果です。  
終了文字列パターンにマッチした文字列だけが削除(空文字列で置換)されますので、マッチしなければ元の文字列が得られます。

**コード**

[code]

    def extract(str, patern):
        import re
        return re.sub(patern, "", str)
    
[/code]

**呼び出しコード**

[code]

    終了文字列パターン = "(aaa|bbb).*"
    対象文字列1 = "AAAaaaZZZ"
    対象文字列2 = "AAAbbbZZZ"
    対象文字列3 = "AAAcccZZZ"
    print("対象文字列1=[" + str(対象文字列1) + "]")
    print("対象文字列2=[" + str(対象文字列2) + "]")
    print("対象文字列3=[" + str(対象文字列3) + "]")
    
    結果1 = extract(対象文字列1, 終了文字列パターン)
    print("結果1=[" + str(結果1) + "]")
    
    結果2 = extract(対象文字列2, 終了文字列パターン)
    print("結果2=[" + str(結果2) + "]")
    
    結果3 = extract(対象文字列3, 終了文字列パターン)
    print("結果3=[" + str(結果3) + "]")
    
[/code]

**結果**

[code]

    終了文字列パターン=[(aaa|bbb).*]
    対象文字列1=[AAAaaaZZZ]
    対象文字列2=[AAAbbbZZZ]
    対象文字列3=[AAAcccZZZ]
    結果1=[AAA]
    結果2=[AAA]
    結果3=[AAAcccZZZ]
    
[/code]


CC BY-SA 4.0
2020-02-22T23:36:29.007
63289
2020-02-22T23:36:29.007
35558
63276
answer


コードの方をいじれるんなら、akira ejiriさんの回答で十分だと思います。

こちらは、コメントに「正規表現自体はソースの外出し」と言うことですので、使う正規表現によって、コードの方をいじったりはできず、正規表現のマッチする範囲自体が切り出したい文字列になっていないといけない、と言う想定での回答になります。

[code]

    import re
    
    a = "AAAaaaZZZ"
    b = "AAAbbbZZZ"
    c = "AAAcccZZZ"
    
    pattern = "(.*?)(?=aaa|bbb|$)"
    
    print(re.match(pattern, a).group(0))
    print(re.match(pattern, b).group(0))
    print(re.match(pattern, c).group(0))
    
[/code]

実行例

[code]

    AAA
    AAA
    AAAcccZZZ
    
[/code]

* * *

マッチに使用しているコードによっては、若干書き換える必要があるかもしれませんが、

  * "aaa"や"bbb"にもマッチしてしまう

→(metropolisさんのコメントにあるように)肯定的先読み`(?=〜)`が使える

  * "aaa"や"bbb"を含まない場合には何にもマッチしません

→対象の"aaa"、"bbb"に加え、終端を表す`$`を同じ並びに入れてやる

と言う形で解決しています。


CC BY-SA 4.0
2020-02-23T00:57:57.853
63290
2020-02-23T00:57:57.853
13972
63276
answer