2010-07-01 9 views
1

파이썬에서 입력 문자열을 구문 분석하고 특정 부분을 추출해야합니다.파이썬에서 문자열의 일부를 추출하십시오.

문자열의 형식은 ...

(xx,yyy,(aa,bb,...)) // Inner parenthesis can hold one or more characters in it 

내가 함수가 XX, YYYY와 BB, AA를 포함하는 목록을 반환 할 것입니다 등

내가 분할을 시도하여 당연히 할 수있는 하지만 괄호 물건의 내가 알고 싶은 경우이 문자열에서 같은 정보를 추출하는 적절한 파이썬 방법

I 작동이 코드를 가지고 있지만, (정규식없이)

그것을 할 수있는 더 좋은 방법이
def processInput(inputStr): 
    value = inputStr.strip()[1:-1] 
    parts = value.split(',', 2) 
    return parts[0], parts[1], (parts[2].strip()[1:-1]).split(',') 
+1

당신은 실제로 단지'평가()'가, 나는 확실히 그것을 추천하지 않을 수 있지만 : –

+0

http://gskinner.com/RegExr/ –

답변

3

을, 당신은 pyparsing을 사용할 수

>>> import pyparsing as p 
>>> ope, clo, com = map(p.Suppress, '(),') 
>>> w = p.Word(p.alphas) 
>>> s = ope + w + com + w + com + ope + p.delimitedList(w) + clo + clo 
>>> x = '(xx,yyy,(aa,bb,cc))' 
>>> list(s.parseString(x)) 
['xx', 'yyy', 'aa', 'bb', 'cc'] 

pyparsing도 있습니다 원하는 경우 결과의 정확한 형식 (예 : 마지막 3 개 항목을 자체 하위 목록으로 그룹화)을 쉽게 제어 할 수 있습니다. 하지만 가장 좋은면은 얼마나 많은 공간을 당신이 그것에 쓰고 싶은지에 따라 자연스럽게 생각합니다. "문법 명세"를 읽을 수있게 만들 수 있습니다 : 열린 괄호, 단어, 쉼표, 단어, 쉼표, 열기 paren, 구분 된 단어 목록, 두 개의 닫힌 괄호 (위의 s에 대한 할당이 너무 읽기 쉽지 않다면 더 긴 식별자를 선택하지 않으면 내 잘못이라고 생각합니다.)

+0

Alex, 당신은 악몽을 퍼트립니다! 나는 아마 우리가 서로 1 분 안에 게시했다고 생각한다! – PaulMcG

+0

@ Paul, yep - 내 글을 쓰기 시작하면서 게시물이 없었기 때문에 반대 의견도 붙어 있기 때문에 꽤 많이 작성해야합니다! –

2

정규 표현식을 사용합시다! 그에 대한

/\(([^,]+),([^,]+),\(([^)]+)\)\)/ 

매치 첫 번째, 두 번째 YYY을 포함, 그룹이 XX가 들어 캡처, ,에 세 번째 분할 당신은 당신의 목록을 가지고있다.

+0

제쳐두고 ...그것은이 XKCD를 생각 나게합니다 : http://xkcd.com/208/ – Caladain

+0

정규 표현식을 사용하는 것은 확실히 좋은 방법입니다. 어쨌든 sortof와 같은 표현식을 역순으로 만들어서 필요한 부분을 추출하는 데 사용합니까? – randomThought

+0

C에는'sscanf' 함수가 있습니다. 그러나 파이썬이 표준 라이브러리에 상응하는지 여부는 모르겠습니다. 누군가 제 3 자 라이브러리에서 구현했을 수도 있습니다. –

1

이 방법이 더 좋지는 모르겠지만 다른 방법이 있습니다. 이전에 제안한 정규 표현식 사용하기

def processInput(inputStr): 
     value = [re.sub('\(*\)*','',i) for i in inputStr.split(',')] 
     return value[0], value[1], value[2:] 

또는 정규 표현식 대신 2 개의 체인 교체 함수를 사용할 수 있습니다.

2

어때? 당신의 괄호 중첩 임의로 깊은 경우

>>> import ast 
>>> import re 
>>> 
>>> s="(xx,yyy,(aa,bb,ccc))" 
>>> x=re.sub("(\w+)",'"\\1"',s) 
# '("xx","yyy",("aa","bb","ccc"))' 
>>> ast.literal_eval(x) 
('xx', 'yyy', ('aa', 'bb', 'ccc')) 
>>> 
3

, 다음하지 않을 것이다 regexen, 당신은 상태 머신 또는 파서가 필요합니다.

from pyparsing import * 

LPAR,RPAR,COMMA = map(Suppress,"(),") 
nestedParens = Forward() 
listword = Word(alphas) | '...' 
nestedParens << Group(LPAR + delimitedList(listword | nestedParens) + RPAR) 

text = "(xx,yyy,(aa,bb,...))" 
results = nestedParens.parseString(text).asList() 
print results 

text = "(xx,yyy,(aa,bb,(dd,ee),ff,...))" 
results = nestedParens.parseString(text).asList() 
print results 

인쇄 : 대한 파싱은 앞으로 미래 선언 클래스를 사용하여 재귀 문법을 지원하면 RE들에 알레르기가 있다면

[['xx', 'yyy', ['aa', 'bb', '...']]] 
[['xx', 'yyy', ['aa', 'bb', ['dd', 'ee'], 'ff', '...']]] 
+0

+1 왜냐하면 내가 아주 기본을 고수하고있는 동안'pyparsing'의 몇 가지 고급 기능을 보여주기 때문입니다 .- –

0

당신의 솔루션은 괜찮습니다 (간단하고 효율적입니다). 데이터 소스를 신뢰하지 않으면 정규식을 사용하여 구문을 제한 할 수 있습니다.

import re 
parser_re = re.compile(r'\(([^,)]+),([^,)]+),\(([^)]+)\)') 
def parse(input): 
    m = parser_re.match(input) 
    if m: 
     first = m.group(1) 
     second = m.group(2) 
     rest = m.group(3).split(",") 
     return (first, second, rest) 
    else: 
     return None 

print parse('(xx,yy,(aa,bb,cc,dd))') 
print parse('xx,yy,(aa,bb,cc,dd)') # doesn't parse, returns None 

# can use this to unpack the various parts. 
# first,second,rest = parse(...) 

인쇄 : 내부 값이 인용 된 경우

('xx', 'yy', ['aa', 'bb', 'cc', 'dd']) 
None 
관련 문제