여러 줄의 텍스트 블록과 일치하는 정규식
여러 줄에 걸쳐 있는 텍스트와 일치할 때 파이썬 정규식이 작동하는 데 약간 어려움을 겪고 있습니다.예제 텍스트는 다음과 같습니다.\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)
빈 줄이 나타날 때까지 줄 1+줄 2+줄 3+등이 됩니다.
궁금한 사람이 있다면, 단백질을 구성하는 아미노산 서열이라고 합니다.
사용해 보십시오.
re.compile(r"^(.+)\n((?:\n.+)+)", re.MULTILINE)
내 생각에 당신의 가장 큰 문제는 당신이 기대하는 것입니다.^
그리고.$
앵커가 라인 피드에 일치하지만 그렇지 않습니다.다중 회선 모드에서,^
새 줄 바로 뒤에 있는 위치와 일치합니다.$
새 줄 바로 앞의 위치와 일치합니다.
또한 새 라인은 라인피드()로 구성될 수 있습니다).\n
), 캐리지 리턴(\r
) 또는 캐리지 리턴+라인 피드(\r\n
) 대상 텍스트가 라인 피드만 사용하는지 확실하지 않으면 정규식의 보다 포괄적인 버전을 사용해야 합니다.
re.compile(r"^(.+)(?:\n|\r\n?)((?:(?:\n|\r\n?).+)+)", re.MULTILINE)
참고로, 당신은 여기서 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
는 "새로운 줄에 도달할 때까지 가능한 많은 대문자와 일치"를 의미합니다.이것은 내가 텍스트 라인이라고 부르는 것을 정의합니다.((?:
텍스트 라인)+)
는 하나 이상의 텍스트 라인과 일치하지만 각 라인을 그룹에 넣지는 않습니다.대신 모든 텍스트 줄을 한 그룹에 넣습니다.- 결승전을 추가할 수 있습니다.
\n
마지막에 두 개의 새 줄을 적용하려는 경우 정규식에서. - 또한, 어떤 종류의 새로운 라인이 생길지 확신할 수 없다면 (
\n
또는\r
또는\r\n
) 을 수정할 때마다\n
타고(?:\n|\r\n?)
.
다음은 여러 줄의 텍스트 블록과 일치하는 정규식입니다.
import re
result = re.findall('(startText)(.+)((?:\n.+)+)(endText)',input)
각 파일이 아미노산 서열 하나만 가지고 있다면, 저는 정규 표현을 전혀 사용하지 않을 것입니다.이와 같은 것입니다.
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
때때로 문자열 내부에서 인라인 플래그로 플래그를 지정하는 것이 편리할 수 있습니다.
"(?m)^A complete line$".
예를 들어 assert Raise Regex를 사용한 단위 검정의 경우입니다.그렇게 하면, 당신은 할 필요가 없습니다.import re
또는 아사트를 호출하기 전에 정규식을 컴파일합니다.
찾기:
^>([^\n\r]+)[\n\r]([A-Z\n\r]+)
\1 = some_summary_text
\2 = 모든 CAP의 라인
편집(이 기능함을 증명):
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)]
#NOTE can be sorter with matches = re.findall(pattern, text, re.MULTILINE)
for m in matches:
print 'Name: %s\nSequence:%s' % (m[0], m[1])
제 취향은.
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 )
이때 문자열로 일부 VariingText가 있고 문자열 목록으로 산이 있습니다.할수있습니다"".join( acids )
하나의 끈을 만드는 것.
저는 이것이 여러 줄의 정규식보다 덜 좌절적이고 더 유연하다고 생각합니다.
언급URL : https://stackoverflow.com/questions/587345/regular-expression-matching-a-multiline-block-of-text
'source' 카테고리의 다른 글
윈도우즈에서 'virtualenv'가 활성화되지 않음 (0) | 2023.07.16 |
---|---|
Python 실행 파일에서 libpython 공유 라이브러리를 찾을 수 없음 (0) | 2023.07.16 |
화력 기지Cloud Firestore를 초기화하려고 할 때 firestore()가 기능하지 않습니다. (0) | 2023.07.16 |
numpy 배열을 튜플로 변환 (0) | 2023.07.16 |
Python: print 명령으로 줄 바꿈 방지 (0) | 2023.07.16 |