정규표현식 (re)

반응형
    반응형

    정규표현식에 대해 설명하겠습니다.

     

    정규표현식은 특정한 패턴과 일치하는 문자열을 검색하거나 치환하거나 제거하는 기능을 가지고 있습니다. 

    이메일 형식 판별이나 전화번호 판별, 자신이 원하는 문자열 판별 등을 할 수 있습니다. 그래서 정규표현식을 이용해 

    스팸메일 걸러내거나 문서를 걸러내는 업무 자동화등을 할 수 있습니다. 참고로 re 모듈을 import 하고 시작할 수 있습니다.

    이번 포스팅에서는 정규표현식의 기초적인 문법만 설명하겠습니다. 

     

     

    기본 패턴

     

    정규식을 사용하려면 메타 문자를 알고 있어야 패턴을 생성해서 원하는 검색을 할 수 있습니다.

    메타 문자 설명
    * 0회 이상 반복 허용
    + 1회 이상 반복 허용
    ? 0회나 1회 반복 허용
    {m} m회 반복 허용
    {m,n} m회부터 n회까지 반복 허용
    . 줄바꿈 문자를 제외한 모든 문자 매칭
    ^ 문자열의 시작과 매칭.
    []안에서 사용되면 not을 의미
    [^a]는 a가 아닌 문자를 찾으라는 요청.
    $ 문자열의 마지막에 매칭
    [] 문자 집합
    [abc] or [a-c] : a,b,c 중 한 문자를 의미
    [a-z] :영어소문자
    [A-Z] : 영어대문자
    [0-9] : 숫자
    [가-힣] : 한글
    | (shift+\) a|b : a 또는 b를 의미.
    () 정규식을 그룹으로 묶는다.
    \\ 문자 자체를 의미
    \d 모든 숫자 매칭. [0-9]와 동일
    \D 숫자가 아닌 모든 문자. [^0-9]
    \s 공백문자와 일치
    \S 공백문자가 아닌 것과 매칭
    \w 숫자 또는 문자.[a-z0-9A-Z]와 동일
    \W 숫자 또는 문자가 아닌것과 매칭 [^a-z0-9A-Z]
    \b 단어의 경계 표현
    단어는 영문자나 숫자의 연속 문자열로 가정한다.
    \B 단어의 경계가 아님을 표현

     

    주요한 것만 예를 들겠습니다.

    import re
    print(re.search(r'abc','123abcdef'))
    print(re.search(r'..\w\w','@#$ABCDabcd'))     #앞에는 찾고자 하는 문자, 뒤에는 찾을대상
    

    첫번째로 abc로 된 문자를 찾아달라는 요청을 했습니다. 참고고 문자열 앞에 r을 붙이면 모든걸 문자로 받아들이라는 얘기입니다. 이스케이프 문자도 그대로 나옵니다. 아무튼 요청대로 abc를 찾았습니다. 만약 abc가 없으면 'None' 으로 나오거나 아무것도 결과로 나오지 않습니다.

    두번째는 모든문자 2개와 영문자2개로 이루어진 것들을 찾아달라고 요청했습니다. 그래서 파이썬이 #$AB 를 찾아줬습니다.

     

    print(re.search(r'[cbm]ed','bed'))
    print(re.search(r'[^abc]aron','daron'))

    이번엔 []을 활용해서 찾아보겠습니다. 

    [cbm]ed 의미는 cbm 중 하나와 ed가 붙어있는 경우를 찾아달라는 의미입니다.

    두번째 [^abc]aron은 abc가 아닌 문자 하나와 aron 이 붙여있는 글자를 찾아달라는 의미입니다.

    마찬가지로 해당글자가 없으면 아무 일도 일어나지 않을것이고 해당글자가 있다면 match 에 나올것입니다.


    반복패턴을 살펴보겠습니다.

    반복패턴은 위 표에서 보신것처럼 +,*,? 으로 정할 수 있습니다. 주의할점은 반복패턴을 사용하면 무조건 많은 부분이 매칭되도록 해서 간혹 원하는 것보다 더 찾아낼 수도 있습니다. 이걸 greedy 하다라고 표현을 하는데

    greedy하지 않도록 하기 위해서 *?,+?로 최소매칭을 구현할 수 있습니다. 

     

    print(re.search(r'<.+>','<html>hello</html>'))
    print(re.search(r'<.+?>','<html>hello</html>'))

    하나는 ?를 붙이지 않았고 하나는 ?를 붙였습니다. 만약에 <html>만을 찾고 싶다면 ?를 붙여야만 되는 것을 볼 수 있습니다. 왜 이렇게 해야하는지 잘 보면 <.+>는 <html>도 되고 <html>hello</html>도 됩니다. 그러니 greedy한 re모듈은 매칭이 많이 되는 <html>hello</html>으로 찾아주는 것입니다. 이런 성질을 염두해주시고 re모듈을 사용하시기 바랍니다.


    ^,$도 유용합니다.

    print(re.search(r'^b\w+a','cananabaa'))
    print(re.search(r'b\w+a$','cananabaa'))

    ^는 맨 앞부터 찾고 $는 맨 뒤부터 찾습니다. 똑같은 글자를 찾았지만 맨앞에 b로 시작하지 않아서 None 이 나오는 것을 볼 수 있습니다. 

     

    파이썬에서 정규표현식 사용하기

    파이썬에서 정규표현식을 쓰려면 re 모듈을 이용합니다.

    간단한 method를 살펴보겠습니다.

     

    search

    가장 바로 할 수 있는 메쏘드로 search를 쓸 수 있습니다. 

    매치가 있다면 span(매치 시작지점 인덱스, 매치 끝지점 인덱스)와 match로 매치된 문자를 보여줍니다.

    print(re.search(r'\d\d\d', 'abc 123'))
    print(re.search(r'\d\d\d','123 abc'))

     

    match

    match는 search와 비슷하지만, 문자열의 시작부터 비교하는게 다릅니다. 시작부터 없으면 None으로 반환합니다.

     

    print(re.match(r'\d\d\d', 'abc 123'))
    print(re.match(r'\d\d\d','123 abc'))

    match, search의 메쏘드

    match, search는 매치된 문자열이 무엇인지 어디서 어디까지 됐는지 등을 다 보여줍니다.

     

    보통은 매치된 문자열만 필요로 하기 때문에 문자열만 나올 수 있게 다음과 같은 메쏘드를 씁니다.

    메쏘드 기능
    groups() 매치된 문자열 모두를 튜플로 출력
    group() 매치된 문자열 출력
    start() 매치 시작지점 인덱스 출력
    end() 매치 끝지점 인덱스 출력
    span() (start(), end())를 튜플로 출력

     

    각 메쏘드는 다음과 같이 나옵니다.

    m = re.match(r'\d\d\d','123 abc')
    m.group()

     

    start, end는 맨 처음과 맨 끝의 인덱스를 가져옵니다. 

    이를 이용해 불필요한 값을 문자열의 슬라이싱을 이용해 지울 수 있습니다.

    group으로 해도 됩니다. 

    m.start()   # 0 출력
    m.end()     # 3 출력
    m.span()    # (0,3) 출력
    
    # 일부만 출력
    m.string([m.start():2]  or m.group()[m.start():2]

     

    group()을 이용하면 매칭 결과를 분리해서 표시할 수 있습니다.

    m= re.search(r'(\w+)@(.+)','text@gmail.com')
    print(m.group(1))
    print(m.group(2))

    (\w+)로 group(1)을 정했고 (.+)를 group(2)로 정했습니다.

     

    groups()를 쓰면 이를 튜플로 한꺼번에 묶을 수 있습니다.

    m= re.search(r'(\w+)@(.+)','text@gmail.com')
    m.groups()

     

    findall

    findall은 뜻 그대로 매칭되는 모든 패턴을 가져옵니다. 한개 이상이 매칭결과로 나올수있어서 리스트 형태로 반환합니다.

    re.findall(r'[\w+]+@[\w.]+','text@gmail.com and text2@gmail.com')

    sub

    sub는 일치하는 모든 패턴을 치환합니다.

    print(re.sub(r'[\w+]+@[\w.]+','abcd','text@gmail.com and text2@gmail.com'))
    print(re.sub(r'[\w+]+@[\w.]+','abcd','text@gmail.com and text2@gmail.com', count =1))
    

    count 로 치환할 갯수를 정할 수 있습니다.

     

    compile

    정규표현식을 저장합니다. 매번 똑같은 정규표현식을 일일히 쓸 필요가 없습니다. 

    email = re.compile(r'[\w+]+@[\w.]+')
    email.findall('text@gmail.com and text2@gmail.com')

     

    마치며..

    이것으로 re모듈에 대한 전반적인 사용방법에 대해 알아봤습니다.

    마지막으로 정규 표현식을 연습할 수 있는 사이트를 링크하고 이번 포스팅을 마치겠습니다.

    https://regex101.com 

     

    Online regex tester and debugger: PHP, PCRE, Python, Golang and JavaScript

    Please wait while the app is loading...

    regex101.com

     

    댓글

    Designed by JB FACTORY

    ....