파이썬(python) – 정규식, 정규표현식(Regular Expression) [두번째]
지난 시간에 정규식의 개념을 잠깐 살펴보았는데요.
이번 시간부터는 python 에서 정규식을 사용하여 문자열 검색을 하는 방법을 실습해보겠습니다.
>>> import re >>> dir(re) ['DEBUG', 'DOTALL', 'I', 'IGNORECASE', 'L', 'LOCALE', 'M', 'MULTILINE', 'S', 'Scanner', 'T', 'TEMPLATE', 'U', 'UNICODE', 'VERBOSE', 'X', '_MAXCACHE', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__version__', '_alphanum', '_cache', '_cache_repl', '_compile', '_compile_repl', '_expand', '_pattern_type', '_pickle', '_subx', 'compile', 'copy_reg', 'error', 'escape', 'findall', 'finditer', 'match', 'purge', 'search', 'split', 'sre_compile', 'sre_parse', 'sub', 'subn', 'sys', 'template'] >>> |
re 모듈에서 제공하는 함수 중에서 가장 많이 사용하는 3 가지를 이용해서 실습을 해보겠습니다.
- search : string 전체를 검색하여 match 되는 첫번째 문자열을 찾음.
<match object> = re.search( pattern, string, flag=0) - match : string 의 첫 문자열만을 비교하여 pattern 과 match 되는지를 확인.
<match object> = re.match( pattern, string, flag=0) - findall : string 전체에서 pattern 과 일치하는 것을 모두 찾아서 list 로 리턴해줌.
[list of groups, list of tuples] = re.findall( pattern, string, flag=0 )
위의 3 함수 모두 인자의 형태는 같습니다. 정규식을 나타내는 pattern 과 원본 string, 그리고 option flag 입니다.
중요한 것은 리턴형인데 이 리턴형을 정확히 알고 있어야만 해당 결과를 이용하여 또 다른 작업을 할 수 있기 때문입니다. 예를 들어 re.search 의 리턴형이 match object 라는 것을 모른 채 마치 string 처럼 취급해서 연산을 하려고 하면 계속해서 오류를 만날겁니다.
match object 는 객체이니만큼 당연히 해당 객체가 제공하는 함수들을 이용하여 연산 및 작업을 해야 합니다.
먼저 간단히 re.search 를 이용해서 다양한 문자열 검색을 시험해볼까요 ?
첫번째 인자로 주어지는 pattern 에는 이전 시간에 배운 정규식 표현들이 사용될 수 있습니다. 정규식 표현들은 여러분이 머리속에 많이 알고 있을수록 상황에 맞게 좀더 예쁜 pattern 을 만들어낼 수 있습니다.
사실 저는 머리가 나빠서 몇 가지밖에 기억하지 못하고 나머지는 찾아보는 편입니다. ^^
# re 모듈 import # search 를 이용하여 iig 문자열 검색 # search 결과 match object 의 group 함수 이용 # search 의 return 형이 match object 임 # 없는 문자열 검색 # 검색 후 return 형을 확인해보니 NoneType # . 은 하나의 문자를 가리킴. 즉 앞에 아무문자나 # 두문자가 온 후 그 다음 문자가 g 인 것을 검색 # i 와 g 사이에 문자 두개가 있는 것을 검색 # 결과가 없는 것임. NoneType # p 와 g 사이 문자 두개 # a 와 c 사이에 한문자가 있는 문자열 검색 # a 와 c 사이 .(점) 문자가 있는 문자열 검색 # a 와 c 사이에 한문자가 있는 문자열 검색 # a.c 라는 문자열 검색 (. 은 . 문자) # : 문자 뒤에 두개의 아무문자나 # : 문자뒤에 아무문자나 1 개 이상 붙은것 |
위의 실습에서 match.group() 이라는 함수를 수행하면 'iig' 라는 문자열을 반환하는 예를 보셨을 겁니다.
그런데, 이런 문자열을 반환하는 함수 이름을 왜 group() 이라고 지었을까요?
궁금하지 않으세요 ? 전 처음에는 그게 궁금하더라구요.
그래서, 좀 찾아봤더니 search 나 match 을 이용하여 검색할 때 첫번째 인자인 pattern 을 여러개를 줄 수 있어서, 결과도 하나의 string 이 아닌 group(tuple) 으로 리턴할 수 있기 때문에 그렇습니다.
다음의 예를 한번 보시죠.
pattern 을 하나하나 소괄호'()'로 묶어서 search 의 인자로 제공했습니다. 첫번째 검색 pattern 은 (ddd) 이고 두번째 검색 pattern 은 (www)입니다.
이렇게 검색하려는 pattern 을 group 으로 한번에 여러 개를 제공한 것입니다.
그러니, 결과도 group 으로 나와야 겠지요. 즉, tuple 로 결과를 묶어서 리턴합니다.
# 2 개의 pattern group 검색 # 결과로 리턴된 group 을 tuple 로 묶어서 보여줌. # 결과 리턴된 각 group 의 string 을 연결해서 보여줌 # 0 번째 group 은 없고 match.group() 과 같은 결과 # 첫번째 group (element)을 string 으로 리턴 # 두번째 group (element)을 string 으로 리턴 # 하나의 pattern group 만으로 검색 # tuple 의 element 는 하나임 # 3 개의 group 검색 |
정규식도 배웠는데 조금만 더 복잡한 것을 시험해볼까요 ?
>>> m = re.search('([w.]+)@([w.]+)', 'blah dp.lee.dp.lee@gmail.com yyxdf @ aa@xx') |
위에서는 두 개의 group pattern 을 제공했는데, 첫번째와 두번째 모두 ([w.]+) 형태로 찾는 것이네요.
이 정규식의 의미는 [ http://kio.zc.bz/Lecture/regexp.html ] 에서 다시 좀 찾아보신 후 의미를 파악해 주세요.
이상 search() 함수를 통해 문자열 검색을 시험해 보았는데요.
match() 함수는 pattern 문자열을 검색 대상 문자열의 맨 첫 문자열과 비교하여 pattern 이 일치하는지를 검사합니다. 일치하지 않으면 NoneType 리턴입니다.
이 점만 search() 함수와 다르고 나머지는 모두 같습니다.
>>> import re # 첫 문자가 안맞으면 false # 문자열 전체 검색이므로 있으면 true |
findall() 함수는 search, match 함수와는 다르게 모든 문자열을 검색하여 match 되는 모든 것을 List 로 리턴한다는 점이 다릅니다.
다음의 예를 보실까요 ?
>>> m = re.findall('([w.]+)@([w.]+)', 'blah dp.leedp.lee@gmail.com yyxdf @ aa.xx@xx.net') # 결과는 match object 가 아니기 때문에 # 결과는 각 pattern group 결과(tuple)가 List 로 묶여진 것임. |
이제 정규식을 이용하여 문자열 검색을 수행하는 방법을 거의 알아본 것 같습니다.
이번 강의는 좀 길었네요.
그런데, 생각해보니 아직 한가지 알려드리지 않은 것이 또 남아있었네요. ㅎㅎ
바로 위의 3 함수의 세번째 인자인 option flag 에 대해 언급해 드리지를 않았네요.
option flag 는 여러분이 부여하지 않아도 default 가 지정되어 있습니다.
하지만, 특수한 경우에는 대소문자 구분을 해서 찾아라... 등 option 을 주면 편리한 경우들이 있습니다.
사용예를 하나만 보여드릴께요. flag 를 여러개 조합해서 부여할 때는 '|' 를 사용하면 됩니다.
즉, re.I | re.M | re.S 이런 방식으로 사용하시면 됩니다.
# default option 으로 사용하면 # 대소문자 구분해서 아무것도 못찾음 # re.I 옵션을 사용하니 대소문자 미구분 # case-insensitive 라고 하죠. |
아래의 표는 사용할 수 있는 option flag 에 대한 간단한 영문 설명입니다. 해석은 각자의 몫으로... ^^
사용할 수 있는 option flag 의 list 를 보고 싶으시면 dir(re)를 하시면 symbol list 가 나올텐데 유심히 보시면 아래의 목록이 모두 나올 것입니다.
항상 책이나 인터넷을 찾기 전에 dir, help 를 애용하는 것 잊지 마세요. ^^
Modifier | Description |
---|---|
re.I | Performs case-insensitive matching. |
re.L | Interprets words according to the current locale.This interpretation affects the alphabetic group (w and W), as well as word boundary behavior (b and B). |
re.M | Makes $ match the end of a line (not just the end of the string) and makes ^ match the start of any line (not just the start of the string). |
re.S | Makes a period (dot) match any character, including a newline. |
re.U | Interprets letters according to the Unicode character set. This flag affects the behavior of w, W, b, B. |
re.X | Permits "cuter" regular expression syntax. It ignores whitespace (except inside a set [] or when escaped by a backslash), and treats unescaped # as a comment marker. |