반응형

 python re 모듈에는 finditer와 findall 메소드가 있습니다. 이 둘에 대해 간단하게 알아봅시다.

 


 먼저, 이 둘을 이해하기 위해, capturing group에 대해서 간단하게 설명을 드리겠습니다. ([0-9]+)([^0-9]*)가 있는데요. () 안에 있는 것은 캡쳐가 되는 패턴을 의미합니다. 하나씩 차례대로 해석해 보면, 숫자 문자로만 이루어진 패턴과, 숫자 문자가 아닌 문자로만 이루어진 패턴이거나 빈 문자열이거나, 이렇게 두 개의 패턴으로 캡쳐가 된다는 의미입니다.

 

 예제를 보겠습니다.

 

  먼저, "2345abcde"는 어떻게 캡쳐될까요? 숫자로만 이루어진 패턴이 "2345"이고, 숫자로 이루어지지 않거나 빈 문자열인 패턴이 뒤에 "abcde"라는 패턴으로 들어옵니다. 따라서 요렇게 캡쳐될 겁니다. 다음 예제 "336"은 어떻게 될까요?

 

 

 요래 캡쳐됩니다. 왜냐면, [^0-9]*는 빈 문자열도 허용하기 때문입니다. 여기까지 이해하셨다면, finditer와 findall에 대해서 이해할 수 있습니다.

 


 먼저 두 함수 다, 일치되는 패턴을 모조리 찾습니다. 캡쳐된 그룹이 패턴에 들어갔을 때랑, 그렇지 않을 때를 예제로 보도록 하겠습니다.

 

 먼저 finditer는 Match object를 리턴합니다. 리턴된 오브젝트를 가지고 m.group(1), m.group(2) 이런 식으로 사용할 수 있습니다.

 

 

 findall은, matches를 리턴합니다. 그런데, 캡쳐된 그룹이 있다면 튜플로 리턴합니다. 이게 뭔 말인지, 아래 예제를 통해서 보겠습니다.

 

 

 5 ~ 7번째 줄을 보면, re.finditer 함수가 있습니다. p는 패턴이고, target은 타겟 문자열을 의미합니다. finditer이 match object를 리턴한다고 되어 있어요. 그리고, 저는 패턴에 2개의 캡쳐 그룹을 리턴할 거라고 했기 때문에, m.group(1), m.group(2)로 캡쳐된 그룹들을 모두 가져올 수 있어요.

 

 1번째는 숫자, 2번째는 빈 문자열이거나 숫자가 아닌 패턴이므로, 2134, sfkj, 325, fasfjkn, 314, njd 순으로 출력되게 됩니다. 다음에, findall은 패턴이 매치되는 것을 모두 찾는데요. 패턴에 캡쳐된 그룹이 있었습니다. 따라서, 이들을 튜플 형태의 리스트로 리턴하게 됩니다.

 

 결과는 위와 같습니다.

 

 이 예제는 어떨까요? 일단 캡쳐된 그룹이 없습니다. 그러니, m.group(1) 이런 거는 쓸 수 없겠네요. m.group(0)은 일치되는 패턴을 출력하는 것이니, match 그룹을 리턴하는 finditer 함수를 썼다면, m.group(0)을 써야 합니다. 다음, 8번째 줄의 for loop를 봅시다. 캡쳐된 그룹이 없기 때문에, 패턴에 일치하는 문자열의 리스트가 반환될 겁니다. 따라서, for loop를 순회하면, 2134, 325, 314 순으로 출력이 될 겁니다.

 

 정말 그런지 결과를 확인해 봤더니 예상했던 결과가 나옵니다.

 

 예제 몇 개만 더 봅시다. 패턴을 요래 바꾸었습니다. 캡쳐가 된 것은 숫자 하나 이상으로 이루어진 패턴입니다. 결과가 어떻게 나올까요? 1번째 loop의 결과는 2134, 325, 314가 순서대로 출력됩니다. 캡쳐가 된 그룹의 1번째 것이 숫자로만 이루어진 패턴이기 때문입니다.

 

 그리고, findall 메소드도 capturing 된 그룹이 있기 때문에, 숫자 패턴이 있는 튜플 형태의 리스트를 뽑아오게 됩니다. 2134, 325, 314 순으로 나오게 되겠습니다.

 

 

 실행 결과는 위와 같습니다.

 

 

 이 프로그램은 어떨까요? 캡쳐된 그룹을 보면, 숫자로만 이루어진 길이 1이상의 패턴, 숫자가 아닌 것으로만 이루어진 길이 1이상의 패턴이 들어온다고 되어 있는데요. 끝에 314를 봅시다. 앞에 그룹에는 매치가 되는데 뒤에 빈 문자열이 온단 말이지요. 빈 문자열은 길이가 0이기 때문에, 2번째 capture에 매치되지는 않습니다.

 

 

 그래서, 결과에 314가 빠지게 됩니다.

 

반응형

댓글을 달아 주세요