質問: '123aBcde' print('*1*') print(re.compile(r'.*(?=.*?[a-z])').search(argStr).group()) print(re.compile(r'.*(?=.*[a-z])').search(argStr).group()) #文字列を切り出すため、肯定先読みの表現の前に「.*」を入れています print('*2*') print(re.compile(r'(.*?[a-z])').search(argStr).group()) print(re.compile(r'(.*[a-z])').search(argStr).group()) ``` **期待値** *1* ~~123a~~ 123(※訂正しました) ~~123aBcde~~ 123aBcd(※訂正しました) *2* 123a 123aBcde **実行** *1* ~~123aBcde~~ 123aBcd(※訂正しました) ・・・(*) ~~123aBcde~~ 123aBcd(※訂正しました) *2* 123a 123aBcde 非貪欲マッチを指定しているので、(*)でも「123a」となると思っていたのですが、 そのようになりませんでした。 (?=.*pattern)と(?=.*?pattern)の実行結果はなぜ同じになってしまうのでしょうか。 ご教示賜りたいです。 ************** すみません、期待値および実行結果に一部タイプミスがあったため、訂正いたしました。 **追記********** 本来やろうとしていたことは、下記のようなバリデーションチェックです。 ・英小文字、英大文字、数字がそれぞれ1文字以上あること ・全体で8文字以上であること これ自体は、「^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$」とすればよいことが確認できました。 ただ、上記の書き方にたどりつくまでにいくつか調べていたところ、 今回質問したように「.?*」という書き方をしているものがありました。 > > passw0rd という文字列であれば、pとして行頭が^(?=.*?[a-z])にマッチしていることになり、また、passw0として行頭が^(?=.*?\d)にマッチしていることになります。 > > > 上記のとおりだと、(*)の実行結果は「123」になるのでは?と思ったのが、今回の質問のきっかけです。
回答: > > **実行** > > > > ``` > *1* > 123aBcde ・・・(*) > 123aBcde > *2* > 123a > 123aBcde > ``` > > Pythonは知りませんが、一般的な正規表現エンジンではあり得ない結果だったので、ideoneで検証したら期待通りの結果でした。 * Ideone.com - D4k4EV - Online Python3 Interpreter & Debugging Tool ``` *1* 123aBcd 123aBcd *2* 123a 123aBcde ``` > > (?=.*pattern)と(?=.*?pattern)の実行結果はなぜ同じになってしまうのでしょうか。 > > > `.*?` の最短一致は**空文字**です。 そして、前方に最長一致があれば、そちらが優先されます。 > > > ``` > print(re.compile(r'.*(?=.*?[a-z])').search(argStr).group()) > ``` > > `.*?` の最短一致は**空文字**なので、この正規表現は `'.*(?=[a-z])'` と同義です。 `.*` は最長一致なので、貪欲に消費します。 ``` 123aBcd ``` Re: chida3 さん