2013-06-27 5 views
0

나는 다음과 같은 텍스트가 :루프 나머지 요소

여기
line, Error = 12, This is the Error 
line, Error = 34, Another Error 
line, Error = 90, Error Three 

내가 가지고 얼마나 멀리입니다 :

theText = 'ERROR: ...' 
ERROR_RE = re.compile(r'^ERROR: <(?P<path>.*):(?P<line>[0-9]+)> (?P<error>.*)$') 
mainName = '\Main.ext' 
# Go through each line 
for fullline in theText.splitlines(): 
    match = self.ERROR_RE.match(fullline) 
    if match: 
     path, line, error = match.group('path'), match.group('line'), match.group('error') 
     if path.endswith(mainName): 
      callSomething(line, error) 
     # else check next line for 'Call Trace:' 
     # check next lines for mainName and get the linenumber 
     # callSomething(linenumber, error) 

ERROR: <C:\Includes\Library1.inc:123> This is the Error 
Call Trace: 
    <C:\Includes\Library2.inc:456> 
    <C:\Includes\Library2.inc:789> 
    <C:\Code\Main.ext:12> 
    <Line:1> 
ERROR: <C:\Includes\Library2.inc:2282> Another Error 
Call Trace: 
    <C:\Code\Main.ext:34> 
    <C:\Code\Main.ext:56> 
    <C:\Code\Main.ext:78> 
    <Line:1> 
ERROR: <C:\Code\Main.ext:90> Error Three 

나는 다음과 같은 정보를 추출하고 싶습니다를

루프 내의 나머지 요소를 반복하는 비법은 무엇입니까?

솔루션 : http://codepad.org/BcYmybin

+0

왜 오류 3은 나머지 오류와 일치하지 않습니까? –

+0

죄송합니다, 명확하지 않습니다. errorText하지만 호출 추적에서 가장 가까운 Main.ext 파일의 줄 번호를 원합니다. 오류 3은 이미 Main.ext에서 발생했습니다 – Adamarla

답변

0

이 교체 :이

 # else check next line for 'Call Trace:' 
     # check next lines for mainName and get the linenumber 
     # callSomething(linenumber, error) 

을 :

match = stackframe_re.match(fullline) 
    if match and error: # if error is defined from earlier when you matched ERROR_RE 
     path, line = match.group('path'), match.group('line') 
     if path.endsWith(mainName): 
      callSomething(line, error) 
      error = None # don't report this error again if you see main again 

참고 들여 쓰기를. 또한 루프가 시작되기 전에 error = None을 초기화하고 callSomething을 처음 호출 한 후에 error = None을 설정하십시오. 일반적으로 내가 제안한 코드는 올바른 형식의 데이터에 대해서는 작동해야하지만, 데이터가 예상 한 형식과 일치하지 않는 경우 오해의 소지가있는 결과를주지 않도록 개선하려고 할 수 있습니다. 당신은 "루프에서 루프 나머지 요소를 말할 때 내가 정말 이해가 안

<C:\Includes\Library2.inc:789> 

당신은 stackframe_re를 작성해야하지만, 예를 들어, 일치하는 RE되어야한다, 무슨 뜻인지 ". 루프는 기본적으로 나머지 요소로 계속됩니다. , 방법, 나머지 라인을 통해 루프에 관한

+0

감사합니다. 나는 한 번에 그것을 할 생각조차하지 않았다. 나는 ERROR 라인을 발견 한 후 중첩 된 루프를 생각하고 있었다. – Adamarla

1

귀하의 질문에 직접 답변 : 경기 후, 다음

lines = theText.splitlines() 
for (linenum, fullline) in enumerate(lines): 

에 루프의 첫 번째 라인을 변경, 당신은에 의해 나머지 라인을 얻을 수 있습니다 내부 루프에서 lines[j]을보고 jlinenum+1에서 시작하여 다음 일치까지 실행됩니다.

그러나 문제를 해결하는 더 매끄러운 방법은 먼저 텍스트를 블록으로 분할하는 것입니다. 이것을하기위한 많은 방법이 있지만, 이전의 perl 사용자 였고, 나의 충동은 정규 표현식을 사용하는 것이다.

# Split into blocks that start with /^ERROR/ and run until either the next 
# /^ERROR/ or until the end of the string. 
# 
# (?m)  - lets '^' and '$' match the beginning/end of each line 
# (?s)  - lets '.' match newlines 
# ^ERROR - triggers the beginning of the match 
# .*?  - grab characters in a non-greedy way, stopping when the following 
#    expression matches 
# (?=^ERROR|$(?!\n)) - match until the next /^ERROR/ or the end of string 
# $(?!\n) - match end of string. Normally '$' suffices but since we turned 
#    on multiline mode with '(?m)' we have to use '(?!\n)$ to prevent 
#    this from matching end-of-line. 
blocks = re.findall('(?ms)^ERROR.*?(?=^ERROR|$(?!\n))', theText) 
+0

끝에 하나의 루프로 만들었지 만 이것은 내가 요청한 방식대로하는 방법에 대한 직접적인 대답입니다. +1. – Adamarla

관련 문제