2016-06-20 15 views
12

목표 : split이 내가 원하는 것을하지 않는 Python RegEx에서 잘라내기를 시도하고 있습니다. 나는 패턴 안에서, 그러나 문자들 사이에서 잘라야한다.패턴 내에서 파이썬 정규식을 사용하여 자름

은 내가 무엇을 찾고 있어요 : 나는 문자열에서 아래의 패턴을 인식해야하고, 파이프의 위치에서 문자열을 분할

. 파이프는 실제로 문자열에있는 것이 아니라 분할하려는 위치를 보여줍니다.

패턴 : CDE|FG

문자열 : ABCDEFGHIJKLMNOCDEFGZYPE

결과 : ['ABCDE', 'FGHIJKLMNOCDE', 'FGZYPE']

내가 시도하는 것 : 내가 괄호로 분할을 사용하는 것 같아

가까운이지만, '아무튼 필요에 따라 검색 패턴을 결과에 첨부하십시오.

re.split('CDE()FG', 'ABCDEFGHIJKLMNOCDEFGZYPE')

가 부여

실제로 필요

['AB', 'HIJKLMNO', 'ZYPE']

,

['ABCDE', 'FGHIJKLMNOCDE', 'FGZYPE']

동기 부여 :

RegEx를 사용하여 연습하고 특정 단백 분해 효소를 사용하여 단백질 분해의 단편을 예측하는 스크립트를 만들기 위해 RegEx를 사용할 수 있는지 확인하고 싶었습니다.

+0

당신에게 허용되지 않은 정규식 기반 솔루션은? – wim

+0

물론입니다! 그러나, 나는 우아함에 가고 있었다. 파이썬 코드 단락을 사용하여 수동으로이 작업을 수행 할 수 있습니다. –

+0

당신이 필요로하는 것은'(? <= CDE) (? = FG)' – sln

답변

7

당신 (이 꽤 아니다, 내가 인정), 즉 "수동"샘플을 처리 할 수 ​​있습니다 그 다음에 split.

>>> pattern = 'CDE|FG' 
>>> s = 'ABCDEFGHIJKLMNOCDEFGZYPE' 
>>> s.replace('CDEFG',pattern).split('|') 
['ABCDE', 'FGHIJKLMNOCDE', 'FGZYPE'] 
+1

정규식과 달리 문자열을 여러 패턴으로 쉽게 나눌 수 있습니다. 그러나 소개하는 제어 문자가 이미 파일에서 사용 중이면 원치 않는 결과가 발생합니다. (이 경우 파이프) –

+2

@Yab. 대답은 정규 표현식 대신 * 더 빠른 대안입니다. OP는 주석에서 비 정규 표현식 응답에 개방적이어서 대답을 언급합니다. 여기서 * pipe *는 데이터 집합에 존재하지 않는다고 가정합니다. 보통 이러한 경우에는 특수 문자와 유니 코드 리터럴을 포함하는 다중 구분 기호가 사용됩니다. 간단한 유스 케이스를 보여주기 위해 사용하지 않았습니다. –

+1

정규 표현식을 _ 필요로하는 경우에는 're.sub'와 동일한 접근법을 사용할 수 있습니다. 예를 들어're (r "(CD [xy]) (FG)", r "\ 1 | \ 2", data)'. – alexis

5

당신은 re.split() 긍정적 "look arounds" 그것을 해결할 수 :

>>> re.split(r"(?<=CDE)(\w+)(?=FG)", s) 
['ABCDE', 'FGHIJKLMNOCDE', 'FGZYPE'] 

주를 절단 시퀀스 중 하나가 빈 문자열 인 경우, 당신은 결과 목록 내부에 빈 문자열을 얻을 것이다.

import re 

s = "ABCDEFGHIJKLMNOCDEFGZYPE" 

cut_sequences = [ 
    ["CDE", "FG"], 
    ["FGHI", ""], 
    ["", "FGHI"] 
] 

for left, right in cut_sequences: 
    items = re.split(r"(?<={left})(\w+)(?={right})".format(left=left, right=right), s) 

    if not left: 
     items = items[1:] 

    if not right: 
     items = items[:-1] 

    print(items) 

인쇄 : 비 정규식 방법은 replace에 파이프 값 패턴 것

['ABCDE', 'FGHIJKLMNOCDE', 'FGZYPE'] 
['ABCDEFGHI', 'JKLMNOCDEFGZYPE'] 
['ABCDE', 'FGHIJKLMNOCDEFGZYPE'] 
+0

나는 이것을 좋아한다. 솔루션을 많이, 그리고 내가 부탁을 않습니다,하지만 일반화하려고 할 때, 나는'FGHI'와 같은 커트 시퀀스를 얻을 수 없습니다. –

+0

@MichaelMolter 네, 여분의 빈 문자열을 첫 번째 분할 항목으로 가져옵니다. 맞습니까? 나는 당신이''FGHI' 나'FGHI |'와 같은 빈 분할 구분 기호를''re.split()':'[1 :]'과'[: -1] '라고 말했다. 저기 .. 감탄할 수있는 더 우아한 방법이 있을지도 몰라. – alecxe

+0

이 솔루션은 너무 잘못되었습니다. "ABCDExxxxxxxFGH"를 세 조각으로 나누면 올바르게 절단됩니다. – alexis

1

더 안전한 비 정규식 솔루션이 될 수 있습니다 :

import re 

def split(string, pattern): 
    """Split the given string in the place indicated by a pipe (|) in the pattern""" 
    safe_splitter = "#@#@SPLIT_HE[email protected]#@#" 
    safe_pattern = pattern.replace("|", safe_splitter) 
    string = string.replace(pattern.replace("|", ""), safe_pattern) 
    return string.split(safe_splitter) 

s = "ABCDEFGHIJKLMNOCDEFGZYPE" 
print(split(s, "CDE|FG")) 
print(split(s, "|FG")) 
print(split(s, "FGH|")) 

https://repl.it/C448

2

는 괄호로 묶어, 당신은 re.split로 분할 할 때 분할 패턴을 유지, 또는 그 부분.

>>> data 
'ABCDEFGHIJKLMNOCDEFGZYPE' 
>>> pieces = re.split(r"(CDE)(FG)", data) 
>>> pieces 
['AB', 'CDE', 'FG', 'HIJKLMNO', 'CDE', 'FG', 'ZYPE'] 

충분히 쉽습니다. 모든 부품이 있지만, 당신이 볼 수 있듯이 그들은 분리되어 있습니다. 그래서 우리는 그들을 재구성해야합니다. 그것은 더 까다로운 부분입니다. 조심스럽게 살펴보면 처음 두 조각, 마지막 두 조각 및 나머지는 3 조각에 합류해야한다는 것을 알 수 있습니다. 목록을 패딩하여 코드를 단순화하지만 성능이 문제가 될 경우 원본 목록 (및 추가 코드 약간)을 사용하여 코드를 작성할 수 있습니다.

>>> pieces = [""] + pieces 
>>> [ "".join(pieces[i:i+3]) for i in range(0,len(pieces), 3) ] 
['ABCDE', 'FGHIJKLMNOCDE', 'FGZYPE'] 

re.split() 모든 캡처 (괄호) 그룹에 대한 조각, 플러스 사이에 무엇에 대한 부분을 보장합니다. 고유 한 그룹화가 필요한보다 복잡한 정규 표현식을 사용하는 경우 캡처되지 않은 그룹을 사용하여 반환 된 데이터의 형식을 동일하게 유지합니다. (그렇지 않으면 재 조립 단계를 조정해야합니다.)

PS. Bhargav Rao가 문자열에 구분자를 삽입 할 것을 제안합니다. 성능이 문제가되지 않는다면, 나는 그것이 맛의 문제라고 생각합니다.

편집 : 다음 목록에 빈 문자열을 추가하지 않고 그것을 할 수있는 (덜 투명) 방법 :

pieces = re.split(r"(CDE)(FG)", data) 
result = [ "".join(pieces[max(i-3,0):i]) for i in range(2,len(pieces)+2, 3) ]