Ravi の正規表現パターンは、場合によっては誤った結果を生成します。
例:
import re
s = """test
word 1
word 2
word 3
test
tutulululalalo
testimony
word A
word B
follow
word X
word Y
test
"""
pat = ('test(?:\w|\s(?!test))+?follow')
print re.findall(pat,s)
#
#result : ['testimony\nword A\nword B\nfollow']
パターンは次のようにする必要があります。
pat = ('test(?=\s)' '(?:\w|\s(?!test(?=\s)))+?' 'follow')
print re.findall(pat,s)
#
#result : ['test \ntutulululalalo\ntestimony\nword A\nword B\nfollow']
それに、OR式の面白みも感じられない。これは機能します:
pat = ('(test(?=\s)' '(?:.(?!test(?=\s)))+?' 'follow)')
print re.findall(pat,s,re.DOTALL)
#
#result : ['test \ntutulululalalo\ntestimony\nword A\nword B\nfollow']
最後に、次のパターンを好みます。最初の「test」と最後の「follow」の間に「test」がないことを 1 回のパスで検証
し、その後に「follow」が続くかどうかを各文字で検証するからです。'(?:\w|\s(?!test(?=\s)))+?'
'(?:.(?!test(?=\s)))+?'
pat = ('test(?=\s)'
'(?!.+?test(?=\s).*?follow)'
'.+?'
'follow')
print re.findall(pat,s,re.DOTALL)
#
#result : ['test \ntutulululalalo\ntestimony\nword A\nword B\nfollow']
.
編集1
Ravi Thapliyal が指摘したように、私の最後の正規表現パターン
pat = ('test(?=\s)'
'(?!.+?test(?=\s).*?follow)'
'.+?'
'follow')
も完璧ではありません。
パターンが気に入らなかったので、このパターンを試してみました。(?!.(?=something))+
私の最後の正規表現パターンは、このありそうもないパターンを置き換えるはずでした。
まあ、それは機能しません。それを機能させるための私のすべての努力は成功しませんでしたが、昔々、機能するようにする微妙な追加部分を備えたそのようなパターンを使用したように思えます。
残念ながら、私は成功しませんでした。いつかうまくいくかもしれないという考えは捨てようと思います。
そこで私は、昔ながらの考えを捨てて、決して好きではなかったパターンが最も明白で、理解しやすく、書きやすいパターンであると明確に考えることにしました。
.
ここで、告白しなければならない 2 つ目の欠点があります。Ravi Thapliyal の正規表現パターンが機能しない場合があることがわかりましたが、考えられる失敗のすべてのケースを考えていませんでした。
ただし、修正するのは簡単です。test(?=\s)
1 つの先読みアサーションだけで書く代わりに(?<=\s)test(?=\s)
、後読みアサーションと先読みアサーションで書くべきでした。
Ravi Thapliyal が作成することを選択しました
が、この作成にはいくつか(?<!\w)(test)\s(?!\1\s)
の欠点が
あります。(?!\\1\s)
(?!\1\s)
(test)
re.findall()
re.finditer()
彼はまた書いています(?:\w|\s(?!\\1\s))*?
。(?!.(?=something))+
ドットを使用しても同じことができるのに、OR 式を使用してパターンを複雑にすることには興味がありません。
さらに、私にとって最もデフォルトのポイントは、Ravi の正規表現パターンが、記号化された文字以外の文字を含む文字列と一致できないことです。\w
これらすべての理由から、次の修正されたソリューションを提案します。
import re
s1 = """test
word 1
word 2
test
word 3
tutulululalalo
protest
testimony
word
unfollow
word B
follow
word X
test
word Y
follow
"""
s2 = """test
word 1
word 2
test
word 3
tutulululalalo
protest
testimony
word ???????
unfollow
word B
follow
word X
test
word Y
follow
"""
.
# eyquem's pattern
fu = '(?<=\s)%s(?=\s)'
a = fu % 'test'
z = fu % 'follow'
pat = ('%s'
'(?:(?!%s).)+?'
'%s'
% (a,a,z))
# Ravi's pattern
patRT = ('(?<!\w)(test)\s'
'(?:\w|\s(?!\\1\s))*?(?<!\w)follow(?!\w)')
for x in (s1,s2):
print x
print re.findall(pat,x,re.DOTALL)
print
print [m.group() for m in re.finditer(patRT,x)]
print
結果
test
word 1
word 2
test
word 3
tutulululalalo
protest
testimony
word
unfollow
word B
follow
word X
test
word Y
follow
['test\nword 3\ntutulululalalo\nprotest\ntestimony\nword\nunfollow\nword B\nfollow', 'test\nword Y\nfollow']
['test\nword 3\ntutulululalalo\nprotest\ntestimony\nword\nunfollow\nword B\nfollow', 'test\nword Y\nfollow']
.
test
word 1
word 2
test
word 3
tutulululalalo
protest
testimony
word ???????
unfollow
word B
follow
word X
test
word Y
follow
['test\nword 3\ntutulululalalo\nprotest\ntestimony\nword ???????\nunfollow\nword B\nfollow', 'test\nword Y\nfollow']
['test\nword Y\nfollow'
]
.
編集2
質問されたとおりに正確に答えるには、次のようにします。
s = """test
word 1
word 2
test
word 3
tutulululalalo
protest
testimony
word ???????
unfollow
word B
follow
word X
test
word Y
follow
"""
fu = '(?<=\s)%s(?=\s)'
a,z = fu % 'test' , fu % 'follow'
pat = ('%s'
'(?:(?!%s).)+?'
'%s'
% (a,a,z))
def ripl(m):
return re.sub('(?m)^(.*)$','**\\1**',m.group())
print re.sub(pat,ripl,s,flags=re.DOTALL)
ripl()
置換を実行するために使用される関数であり、RegexMatch オブジェクトの形式で各一致を受け取り、置換を行うために によって使用される変換された部分を返しますre.sub()
。