2009-02-25 6 views
60

여러 줄에 걸쳐있는 텍스트와 비교할 때 파이썬 정규식을 사용하는 데 약간의 문제가 있습니다. 'some_Varying_TEXT'부분, 그리고 그것을 아래 두 줄을 오는 대문자 텍스트 줄의 모든 : 예제 텍스트여러 줄의 텍스트와 일치하는 정규식

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). 

나는 두 가지를 캡처하고 싶습니다 ('\ n을'은 줄 바꿈이)입니다 하나의 캡처 (나는 나중에 개행 문자를 제거 할 수있다). 나는 몇 가지 방법으로 시도했다 :

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)이 일부일 것입니다 _ 다양 함 _ 빈 줄이 나올 때까지 텍스트 및 그룹 (2)을 line1 + line2 + line3 + 등으로 지정하십시오.

호기심이있는 사람은 단백질을 구성하는 아미노산 서열로 생각됩니다.

+0

첫 번째 줄과 대문자 텍스트 외에 다른 파일이 있습니까? 나는 개행 문자에서 모든 텍스트를 분리하고 첫 번째 요소를 "some_Varying_TEXT"로 사용하는 대신 정규식을 사용하는 이유를 모르겠습니다. – UncleZeiv

+2

예, 정규식은 잘못된 도구입니다. – hop

+0

샘플 텍스트에 '>'문자가 없습니다. 그럴까요? – MiniQuark

답변

81

이 시도 :

re.compile(r"^(.+)\n((?:\n.+)+)", re.MULTILINE) 

나는 당신의 가장 큰 문제는 당신이 줄 바꿈과 일치하도록 ^$ 앵커를 기대하고 있다는 생각하지만, 그들은하지 않습니다. 여러 줄 모드에서 ^은 즉시 위치와 일치하고 개행 다음에 $이 바로 일치합니다. 앞에 개행이 있습니다.

개행 문자는 줄 바꿈 (\ n), 캐리지 리턴 (\ r) 또는 캐리지 리턴 + 줄 바꿈 (\ r \ n)으로 구성 될 수 있습니다. 당신이 당신의 목표 텍스트는 줄 바꿈을 사용하지 특정 경우에, 당신은 정규식이 더 포함 된 버전을 사용해야합니다 : BTW

re.compile(r"^(.+)(?:\n|\r\n?)((?:(?:\n|\r\n?).+)+)", re.MULTILINE) 

, 당신은 여기에 DOTALL 수정을 사용하지 않으을; 도트가 의 모든 내용과 일치한다는 사실에 의거하여 개행을 사용합니다.

+0

빈 줄 두번째 줄에있는 텍스트 파일과이 정규 표현식이 일치하지 않게하려면 정규 표현식의 두 번째 점을 [A-Z]로 대체해야합니다. ;-) – MiniQuark

+0

제 생각에 대상 파일은 빈 줄 대 비어 있지 않은 줄의 명확한 (반복되는) 패턴을 따르므로 [AZ]를 지정할 필요는 없지만 아마 해를 끼치 지 않을 것입니다 , 어느 쪽이든. –

+0

이 솔루션은 아름답게 작동했습니다. 제쳐두고, 나는 분명히 상황을 충분히 분명히하지 않았기 때문에 (또한이 응답의 지각에 대해서도) 사과드립니다. 당신의 도움을 주셔서 감사합니다! – Jan

1

찾기 :

^>([^\n\r]+)[\n\r]([A-Z\n\r]+) 

\ 1 = some_varying_text 모든 CAPS의

\ 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]) 
+0

나에게 잘못 보입니다. 이걸 시험해 봤어? – Triptych

+0

그렇습니다. 몇 가지 코드를 추가했습니다. –

+0

불행히도이 정규식은 빈 줄로 구분 된 대문자 그룹과도 일치합니다. 그래도 큰 문제가 아닐 수도 있습니다. – MiniQuark

14

이 작동 :

>>> 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 수단 "가능한 한 일치 많은 대문자 당신이 줄 바꿈에 도달 할 때까지.이 내가 텍스트 라인를 호출을 정의합니다.
  • ((?:텍스트 라인)+)이 일치 하나 이상의 textlines을 의미하지만,하지 그룹의 각 라인을 넣어. 대신, 하나 개의 그룹에 모든textlines에게을 넣어. 당신은 이중 줄 바꿈을 적용하려는 경우
  • 당신은 정규 표현식에 최종 \n를 추가 할 수 있습니다 결국.또한
  • , 당신은 당신이 (\n 또는 \r 또는 \r\n가) 그럼 그냥 (?:\n|\r\n?)에 의해 \n의 모든 발생을 교체하여 정규 표현식을 수정 얻을 것이다 개행의 어떤 유형에 대한 확실하지 않은 경우.
+0

match()는 대상 텍스트의 맨 처음에 하나의 일치를 반환하지만 OP는 파일 당 수백 개의 일치가 있다고합니다. 대신 finditer()를 사용하는 것이 좋습니다. –

+1

@Alan : 방금 고쳤습니다. 고마워요. – MiniQuark

1

내 기호.

이 시점에서 someVaryingText를 문자열로, 산도를 문자열 목록으로 사용합니다. "".join(acids)을 사용하면 단일 문자열을 만들 수 있습니다.

이 방법은 여러 줄로 된 정규식보다 덜 불편하고 유연합니다.

4

각 파일에 하나의 아미노산 서열 만있는 경우 정규 표현식을 전혀 사용하지 않습니다. 그냥 이런 식으로 :

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 
+0

더 많은 로직이 추가되는 경우, 단 하나만 있다면 가장 쉬운 방법이고, 더 많이 사용하는 것이 가장 쉽습니다. 이 특정 데이터 세트에는 약 885 개의 단백질이 있습니다. 정규식을 처리 할 수 ​​있어야한다고 생각했습니다. – Jan

관련 문제