2点失礼します。
完全に正規表現ベースではないソリューションを提案します。純粋な正規表現ソリューションが必要だと読みました。しかし、私は興味深い問題に取り組み、この問題に正規表現を使用すると問題が過度に複雑になっているとすぐに結論付けました。純粋な正規表現ソリューションでは答えられませんでした。以下のものを見つけたので、それらを示します。たぶん、彼らはあなたにアイデアを与えるかもしれません。
私は C# や .NET を知りません。Python だけです。正規表現はすべての言語でほぼ同じなので、正規表現だけで答えようと思ったので、問題について調べ始めました。とにかく理解しやすいと思うので、Pythonでのソリューションをすべて同じように示します。
一意の正規表現を使用して、テキスト内で必要な文字のすべての出現をキャプチャすることは非常に難しいと思います。複数の行で複数の文字を見つけることは、一致でネストされた一致を見つける問題のように思えるからです (おそらく私は十分なスキルがありませんか?正規表現で)。
そこで、主にすべての行のすべての文字の出現を検索してリストに入れ、次にリストをスライスして希望する出現を選択する方がよいと考えました。
行内の文字を検索する場合、最初は正規表現で問題ないように思えました。SO関数selectRE()を使用したソリューション。
その後、行内の文字を選択することは、便利なインデックスで行をスライスすることと同じであり、リストをスライスすることと同じであることに気付きました。したがって、関数 select() です。
2 つの解をまとめて与えるので、2 つの関数の 2 つの結果が等しいことを確認できます。
import re
def selectRE(a,which_chars,b,x,which_lines,y,ch):
ch = ch[:-1] if ch[1]=='\n' else ch # to obtain an exact number of lines
NL = ch.count('\n') +1 # number of lines
def pat(a,which_chars,b):
if which_chars=='to':
print repr(('.{'+str(a-1)+'}' if a else '') + '(.{'+str(b-a+1)+'}).*(?:\n|$)')
return re.compile(('.{'+str(a-1)+'}' if a else '') + '(.{'+str(b-a+1)+'}).*(?:\n|$)')
elif which_chars=='before':
print repr('.*(.{'+str(a)+'})'+('.{'+str(b)+'}' if b else '')+'(?:\n|$)')
return re.compile('.*(.{'+str(a)+'})'+('.{'+str(b)+'}' if b else '')+'(?:\n|$)')
elif which_chars=='after':
print repr(('.{'+str(b)+'}' if b else '')+'(.{'+str(a)+'}).*(?:\n|$)')
return re.compile(('.{'+str(b)+'}' if b else '')+'(.{'+str(a)+'}).*(?:\n|$)')
if which_lines=='to' : x = x-1
elif which_lines=='before': x,y = NL-x-y,NL-y
elif which_lines=='after' : x,y = y,y+x
return pat(a,which_chars,b).findall(ch)[x:y]
def select(a,which_chars,b,x,which_lines,y,ch):
ch = ch[:-1] if ch[1]=='\n' else ch # to obtain an exact number of lines
NL = ch.count('\n') +1 # number of lines
if which_chars=='to' : a = a-1
elif which_chars=='after' : a,b = b,a+b
if which_lines=='to' : x = x-1
elif which_lines=='before': x,y = NL-x-y,NL-y
elif which_lines=='after' : x,y = y,y+x
return [ line[len(line)-a-b:len(line)-b] if which_chars=='before' else line[a:b]
for i,line in enumerate(ch.splitlines()) if x<=i<y ]
ch = '''line1 blah 1
line2 blah 2
line3 blah 3
line4 blah 4
line5 blah 5
line6 blah 6
'''
print ch,'\n'
print 'Characters 3-6 of lines 3-5. A total of 3 matches.'
print selectRE(3,'to',6,3,'to',5,ch)
print select(3,'to',6,3,'to',5,ch)
print
print 'Characters 1-5 of lines 4-5. A total of 2 matches.'
print selectRE(1,'to',5,4,'to',5,ch)
print select(1,'to',5,4,'to',5,ch)
print
print '7 characters before the last 3 chars of lines 2-6. A total of 5 matches.'
print selectRE(7,'before',3,2,'to',6,ch)
print select(7,'before',3,2,'to',6,ch)
print
print '6 characters before the 2 last characters of 3 lines before the 3 last lines.'
print selectRE(6,'before',2,3,'before',3,ch)
print select(6,'before',2,3,'before',3,ch)
print
print '4 last characters of 2 lines before 1 last line. A total of 2 matches.'
print selectRE(4,'before',0,2,'before',1,ch)
print select(4,'before',0,2,'before',1,ch)
print
print 'last 1 character of 4 last lines. A total of 2 matches.'
print selectRE(1,'before',0,4,'before',0,ch)
print select(1,'before',0,4,'before',0,ch)
print
print '7 characters before the last 3 chars of 3 lines after the 2 first lines. A total of 5 matches.'
print selectRE(7,'before',3,3,'after',2,ch)
print select(7,'before',3,3,'after',2,ch)
print
print '5 characters before the 3 last chars of the 5 first lines'
print selectRE(5,'before',3,5,'after',0,ch)
print select(5,'before',3,5,'after',0,ch)
print
print 'Characters 3-6 of the 4 first lines'
print selectRE(3,'to',6,4,'after',0,ch)
print select(3,'to',6,4,'after',0,ch)
print
print '9 characters after the 2 first chars of the 3 lines after the 1 first line'
print selectRE(9,'after',2,3,'after',1,ch)
print select(9,'after',2,3,'after',1,ch)
結果
line1 blah 1
line2 blah 2
line3 blah 3
line4 blah 4
line5 blah 5
line6 blah 6
Characters 3-6 of lines 3-5. A total of 3 matches.
'.{2}(.{4}).*(?:\n|$)'
['ne3 ', 'ne4 ', 'ne5 ']
['ne3 ', 'ne4 ', 'ne5 ']
Characters 1-5 of lines 4-5. A total of 2 matches.
'.{0}(.{5}).*(?:\n|$)'
['line4', 'line5']
['line4', 'line5']
7 characters before the last 3 chars of lines 2-6. A total of 5 matches.
'.*(.{7}).{3}(?:\n|$)'
['ne2 bla', 'ne3 bla', 'ne4 bla', 'ne5 bla', 'ne6 bla']
['ne2 bla', 'ne3 bla', 'ne4 bla', 'ne5 bla', 'ne6 bla']
6 characters before the 2 last characters of 3 lines before the 3 last lines.
'.*(.{6}).{2}(?:\n|$)'
['2 blah', '3 blah', '4 blah']
['2 blah', '3 blah', '4 blah']
4 last characters of 2 lines before 1 last line. A total of 2 matches.
'.*(.{4})(?:\n|$)'
['ah 5', 'ah 6']
['ah 5', 'ah 6']
last 1 character of 4 last lines. A total of 2 matches.
'.*(.{1})(?:\n|$)'
['4', '5', '6']
['4', '5', '6']
7 characters before the last 3 chars of 3 lines after the 2 first lines. A total of 5 matches.
'.*(.{7}).{3}(?:\n|$)'
['ne3 bla', 'ne4 bla', 'ne5 bla']
['ne3 bla', 'ne4 bla', 'ne5 bla']
5 characters before the 3 last chars of the 5 first lines
'.*(.{5}).{3}(?:\n|$)'
['1 bla', '2 bla', '3 bla', '4 bla', '5 bla']
['1 bla', '2 bla', '3 bla', '4 bla', '5 bla']
Characters 3-6 of the 4 first lines
'.{2}(.{4}).*(?:\n|$)'
['ne1 ', 'ne2 ', 'ne3 ', 'ne4 ']
['ne1 ', 'ne2 ', 'ne3 ', 'ne4 ']
9 characters after the 2 first chars of the 3 lines after the 1 first line
'.{2}(.{9}).*(?:\n|$)'
['ne2 blah ', 'ne3 blah ', 'ne4 blah ']
['ne2 blah ', 'ne3 blah ', 'ne4 blah ']
そして今、私はティム・ピーツカーのトリッキーな解決策を研究します