source

여러 줄의 텍스트 블록과 일치하는 정규식

ittop 2023. 7. 16. 17:57
반응형

여러 줄의 텍스트 블록과 일치하는 정규식

여러 줄에 걸쳐 있는 텍스트와 일치할 때 파이썬 정규식이 작동하는 데 약간 어려움을 겪고 있습니다.예제 텍스트는 다음과 같습니다.\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

반응형