여러 줄에 걸친 텍스트와 일치시킬 때 Python 정규식을 작동시키는 데 약간의 문제가 있습니다. 예제 텍스트는 다음과 같습니다 ( ‘\ n’는 개행)
some Varying TEXT\n
\n
DSJFKDAFJKDAFJDSAKFJADSFLKDLAFKDSAF\n
[more of the above, ending with a newline]\n
[yep, there is a variable number of lines here]\n
\n
(repeat the above a few hundred times).
두 가지를 캡처하고 싶습니다. ‘some_Varying_TEXT’부분과 한 번의 캡처에서 두 줄 아래에 오는 모든 대문자 텍스트 줄입니다 (나중에 줄 바꿈 문자를 제거 할 수 있음). 몇 가지 접근 방식을 시도했습니다.
re.compile(r"^>(\w+)$$([.$]+)^$", re.MULTILINE) # try to capture both parts
re.compile(r"(^[^>][\w\s]+)$", re.MULTILINE|re.DOTALL) # just textlines
운없이 많은 변형이 있습니다. 마지막 하나는 텍스트 줄을 하나씩 일치시키는 것 같습니다. 첫 번째 부분은 잡을 수 있지만 문제 없습니다. 그러나 대문자 텍스트의 4-5 줄을 잡을 수없는 것 같습니다. 빈 줄이 나타날 때까지 match.group (1)을 some_Varying_Text로, group (2)를 line1 + line2 + line3 + etc로 만들고 싶습니다.
궁금한 사람이 있다면 단백질을 구성하는 일련의 아미노산이어야합니다.
답변
이 시도:
re.compile(r"^(.+)\n((?:\n.+)+)", re.MULTILINE)
가장 큰 문제는 ^
및 $
앵커가 줄 바꿈과 일치 할 것으로 예상 하지만 그렇지 않다는 것입니다. 여러 줄 모드에서 줄 바꿈 ^
바로 뒤$
의 위치와 바로 앞 의 위치를 찾습니다. 찾습니다.
줄 바꿈은 줄 바꿈 (\ n), 캐리지 리턴 (\ r) 또는 캐리지 리턴 + 줄 바꿈 (\ r \ n)으로 구성 될 수 있습니다. 대상 텍스트가 줄 바꿈 만 사용하는지 확실하지 않은 경우보다 포괄적 인 정규식 버전을 사용해야합니다.
re.compile(r"^(.+)(?:\n|\r\n?)((?:(?:\n|\r\n?).+)+)", re.MULTILINE)
BTW, 여기서 DOTALL 수정자를 사용하고 싶지 않습니다. 점이 줄 바꿈을 제외한 모든 것과 일치한다는 사실에 의존 하고 있습니다.
답변
이것은 작동합니다.
>>> import re
>>> rx_sequence=re.compile(r"^(.+?)\n\n((?:[A-Z]+\n)+)",re.MULTILINE)
>>> rx_blanks=re.compile(r"\W+") # to remove blanks and newlines
>>> text="""Some varying text1
...
... AAABBBBBBCCCCCCDDDDDDD
... EEEEEEEFFFFFFFFGGGGGGG
... HHHHHHIIIIIJJJJJJJKKKK
...
... Some varying text 2
...
... LLLLLMMMMMMNNNNNNNOOOO
... PPPPPPPQQQQQQRRRRRRSSS
... TTTTTUUUUUVVVVVVWWWWWW
... """
>>> for match in rx_sequence.finditer(text):
... title, sequence = match.groups()
... title = title.strip()
... sequence = rx_blanks.sub("",sequence)
... print "Title:",title
... print "Sequence:",sequence
... print
...
Title: Some varying text1
Sequence: AAABBBBBBCCCCCCDDDDDDDEEEEEEEFFFFFFFFGGGGGGGHHHHHHIIIIIJJJJJJJKKKK
Title: Some varying text 2
Sequence: LLLLLMMMMMMNNNNNNNOOOOPPPPPPPQQQQQQRRRRRRSSSTTTTTUUUUUVVVVVVWWWWWW
이 정규식에 대한 몇 가지 설명이 유용 할 수 있습니다. ^(.+?)\n\n((?:[A-Z]+\n)+)
- 첫 번째 문자 (
^
)는 “행의 시작에서 시작”을 의미합니다. 개행 자체와는 일치하지 않는다는 점에 유의하십시오 ($의 경우 동일 : “개행 바로 앞”을 의미하지만 개행 자체와는 일치하지 않음). - 그런 다음
(.+?)\n\n
“두 줄 바꿈에 도달 할 때까지 가능한 한 적은 수의 문자 (모든 문자 허용) 일치”를 의미합니다. 결과 (줄 바꿈없이)는 첫 번째 그룹에 배치됩니다. [A-Z]+\n
“줄 바꿈에 도달 할 때까지 가능한 한 많은 대문자와 일치합니다. 이것은 내가 textline 이라고 부르는 것을 정의합니다 .((?:
textline)+)
은 하나 이상의 textline 과 일치 하지만 각 줄을 그룹에 넣지 않음을 의미 합니다. 대신 넣어 모든 textlines을 한 그룹.\n
끝에 이중 줄 바꿈을 적용하려면 정규식에 final 을 추가 할 수 있습니다 .- 또한 어떤 유형의 줄 바꿈을 얻을지 (
\n
또는\r
또는\r\n
) 확실하지 않은 경우 모든 항목을\n
로 대체하여 정규식을 수정하십시오(?:\n|\r\n?)
.
답변
각 파일에 아미노산 시퀀스가 하나만 있으면 정규식을 전혀 사용하지 않습니다. 다음과 같이 :
def read_amino_acid_sequence(path):
with open(path) as sequence_file:
title = sequence_file.readline() # read 1st line
aminoacid_sequence = sequence_file.read() # read the rest
# some cleanup, if necessary
title = title.strip() # remove trailing white spaces and newline
aminoacid_sequence = aminoacid_sequence.replace(" ","").replace("\n","")
return title, aminoacid_sequence
답변
찾기:
^>([^\n\r]+)[\n\r]([A-Z\n\r]+)
\ 1 = some_varying_text
\ 2 = 모든 대문자 라인
편집 (작동한다는 증거) :
text = """> some_Varying_TEXT
DSJFKDAFJKDAFJDSAKFJADSFLKDLAFKDSAF
GATACAACATAGGATACA
GGGGGAAAAAAAATTTTTTTTT
CCCCAAAA
> some_Varying_TEXT2
DJASDFHKJFHKSDHF
HHASGDFTERYTERE
GAGAGAGAGAG
PPPPPAAAAAAAAAAAAAAAP
"""
import re
regex = re.compile(r'^>([^\n\r]+)[\n\r]([A-Z\n\r]+)', re.MULTILINE)
matches = [m.groups() for m in regex.finditer(text)]
for m in matches:
print 'Name: %s\nSequence:%s' % (m[0], m[1])
답변
다음은 여러 줄 텍스트 블록과 일치하는 정규식입니다.
import re
result = re.findall('(startText)(.+)((?:\n.+)+)(endText)',input)
답변
내 취향.
lineIter= iter(aFile)
for line in lineIter:
if line.startswith( ">" ):
someVaryingText= line
break
assert len( lineIter.next().strip() ) == 0
acids= []
for line in lineIter:
if len(line.strip()) == 0:
break
acids.append( line )
이 시점에서 someVaryingText를 문자열로, 산을 문자열 목록으로 사용합니다. 넌 할 수있어"".join( acids )
단일 문자열을 만들 .
여러 줄 정규식보다 덜 답답하고 유연합니다.