본문 바로가기
python

[python]파이썬 - 정규표현식

by skysline 2023. 1. 26.
반응형

정규식

  • 정규표현식은 복잡한 문자열을 처리할 때 사용하는 기법
  • 파이썬만의 고유한 기법이 아니라 문자열을 처리하는 모든 곳에서 사용
 
data = "나의 전화번호는 010-0000-0000 입니다. 너의 전화번호는 010-1111-1111 입니다."
 
 
  • 텍스트의 규칙을 보니 띄어쓰기 기준으로 나누자
  • 전화번호의 특징이 하이픈이 사이에 2개가 있다.
  • 전화번호의 특징이 첫 3자리 ,두번째 4자리, 세번째 4자리 형식이다.
 
phone_list = []
for item in data.split():
    item = item.split("-")

    cond_list = []
    if len(item) == 3:
        cond = item[0].isdigit() and len(item[0]) == 3
        cond_list.append(cond)
        cond = item[1].isdigit() and len(item[1]) == 4
        cond_list.append(cond)
        cond = item[2].isdigit() and len(item[2]) == 4
        cond_list.append(cond)

    if sum(cond_list) == 3:
        phone_list.append("-".join(item))
phone_list
 
['010-0000-0000', '010-1111-1111']
 
 
 
data = "나의 전화번호는 010-0000-0000 입니다. 너의 전화번호는 010-1111-1111 입니다."
import re
pat = re.complie("\d{3}-\d{4}-\d{4}")
phone_list = pat.findall(data)
phone_list
 
['010-0000-0000', '010-1111-1111']
 

re(regular expression) 모듈

  • 파이썬의 정규표현식을 지원하기 위한 모듈
 
  • match 함수
    • pattern 맞는 문자열로 시작하는지 검사하고 매칭이 되면 match 객체를 반환하고 그렇지 않으면 None 반환한다.
 
 
import re
data = "나의 전화번호는 010-0000-0000 입니다. 너의 전화번호는 010-1111-1111 입니다."
print(re.match("나의",data))
print(re.match("전화",data))
 
<re.Match object; span=(0, 2), match='나의'>
None
 
match = re.match("나의",data)
match.group()
 
 
 
  • search 함수
    • pattern에 맞는 문자열을 검사하고 매칭되면 바로 match 객체를 반환한다. 매칭이 안되면 None을 반환
 
 
data = "나의 전화번호는 010-0000-0000 입니다. 너의 전화번호는 010-1111-1111 입니다."
re.search("전화",data)
 
<re.Match object; span=(3, 5), match='전화'>
 
  • findall 함수
    • 정규식과 매칭되는 모든 문자열을 리스트로 반환한다.
 
re.findall("번호",data)
 
['번호', '번호']
 
  • sub 함수
    • 정규식과 매칭되는 부분을 치환해준다.
data = "나의 전화번호는 010-0000-0000 입니다. 너의 전화번호는 010-1111-1111 입니다."
re.sub("전화번호","핸드폰번호",data)
 
 
 

메타문자

  • 메타문자란 원래 그문자가 가진 뜻이 아닌 특별한 용도로 사용하는 문자
  • \ ^ $ . [ ] ( ) * + ? { }
 
  • . : 줄바꿈 문자(\n)를 제외한 모든 문자와 매치
 
 
 
data = "abc a\nc a c"
re.findall("a.c",data)
 
['abc', 'a c']
 
  • * : 바로 앞에 문자가 0번이상 반복할 경우 매치
data = "abc ac abbc a c"
re.findall("ab*c",data)
 
['abc', 'ac', 'abbc']
 
  • + : 바로 앞에 문자가 1번 이상 반복할 경우 매치
 
data = "abc ac abbbc"
re.findall("ab+c",data) 
 
['abc', 'abbbc']
 
 
data = "나는 말했다 '오늘 행복하다' 라고..."
re.findall("\'.+\'",data)
 
["'오늘 행복하다'"]
 
re.findall("\'(.+)\'",data)
 
['오늘 행복하다']
 
  • 반복 횟수를 제한하고 싶다면?
    • {m,n}: 바로 앞에 문자의 반복횟수가 m번에서 n번사이
    • {m} : 바로 앞에 문자의 반복횟수가 m번
    • {m,}: 바로 앞에 문자의 반복횟수가 m번 이상
    • {,n}: 바로 앞에 문자의 반복횟수가 n번 이하
data = "abc ac abbbc abbbbc"
re.findall("ab{1,3}c",data)
 
['abc', 'abbbc']
 
data = "abc ac abbbc abbbbc"
re.findall("ab{4}c",data)
 
['abbbbc']
 
data = "abc ac abbbc abbbbc"
re.findall("ab{1,}c",data) # ab+c
 
['abc', 'abbbc', 'abbbbc']
 
data = "abc ac abbbc abbbbc"
re.findall("ab{0,}c",data) # ab*c
 
['abc', 'ac', 'abbbc', 'abbbbc']
 
data = "abc ac abbbc abbbbc"
re.findall("ab{,3}c",data) 
 
['abc', 'ac', 'abbbc']
 
  • ? : 반복은 아니지만 앞에 문자가 있거나 없거나를 의미
 
data = "abc ac abbbc abbbbc"
re.findall("ab?c",data) # ab{0,1}c
 
['abc', 'ac']
 
  • [] : [] 사이의 문자들과 매칭이라는 의미
data = "abc ac acc acb"
re.findall("a[bc]c",data) 
 
['abc', 'acc']
 
  • 대괄호 안에서는 메타문자 역할을 안한다.
data = "abc a+c a.c a?c"
re.findall("a[+.?]c",data)
 
['a+c', 'a.c', 'a?c']
data = "abc a[c a]c"
re.findall("a[\[\]]c",data)
 
['a[c', 'a]c']
 
  • 하이픈(-) 사용하기
    • [a-zA-Z] : 모든 알파벳과 매치
    • [0-9] : 모든 숫자와 매치
data = "python 3.10.5"
re.findall("[0-9a-zA-Z. ]",data)
 
['p', 'y', 't', 'h', 'o', 'n', ' ', '3', '.', '1', '0', '.', '5']
 
data = "python 3.10.5"
re.findall("[0-9a-zA-Z.]+",data)
 
['python', '3.10.5']
 
data = "파이썬 버전은 3.10.5"
re.findall("[가-힣]+",data)
 
['파이썬', '버전은']
 
data = "파이썬 버전은 3.10.5 ㅋㅋㅋ ㅜㅜ"
re.findall("[ㅏ-ㅣ가-힣ㄱ-ㅎ]+",data)
 
['파이썬', '버전은', 'ㅋㅋㅋ', 'ㅜㅜ']
 
  • \d : [0-9] 동일
  • \w : [a-zA-Z0-9_] 동일
data = "python 3_10_5"
re.findall("\w+",data) 
 
['python', '3_10_5']
 
re.findall("\d+",data)
 
['3', '10', '5']
 
  • [^]: ^ 대괄호 안에 있을 경우는 not을 의미한다.
data = "python 3.10.5"
re.findall("[^\d. ]+",data)
 
['python']
 
  • ^ : 검사하고자하는 문자열에 정규식에 맞는 문자로 시작하는지를 검사한다.
  • $ : 검사하고자하는 문자열에 정규식에 맞는 문자로 끝나는지를 검사한다.
phone = "P010-0000-0000d"
match = re.search("^\d{3}-\d{4}-\d{4}$",phone) 
match
 
data = """
연월일 형식에 문자열을 추출해 보시오.
다음은 2002-06-09 형식의 날짜이다.
이것도 2002/10/19 형식의 날짜이다.
010-0000-0000
출력 예시처럼 담아주세요.
"""
Output:
['2002-06-09', '2002/10/19']
data = """
연월일 형식에 문자열을 추출해 보시오.
다음은 2002-06-09 형식의 날짜이다.
이것도 2002/10/19 형식의 날짜이다.
010-0000-0000
출력 예시처럼 담아주세요.
"""
pat = "\d{4}[-/]\d{2}[-/]\d{2}"
re.findall(pat,data)
 
['2002-06-09', '2002/10/19']
 
data = """
다음의 html 에서 태그를 제거해서 출력 예시와 같은 문자열을 만들어주세요.
<div>
    https://www.naver.com">클릭시 href 속성 값의 </a href="링크로 이동하는 태그</a>
    <img src="image.jpg">src 속성에 이미지를 브라우저에 나타내주는 태그</img>
    <ul>
        <li>ul 태그와 함께 목록을 생성해주는 태그</li>
        <li>ul 태그와 함께 목록을 생성해주는 태그</li>
    </ul>
    <p>문단을 의미하는 태그</p>
    <br memo="줄바꿈을 해주는 태그">
</div>
"""
Output:

다음의 html 에서 태그를 제거해서 출력 예시와 같은 문자열을 만들어주세요.

    클릭시 href 속성 값의 링크로 이동하는 태그
    src 속성에 이미지를 브라우저에 나타내주는 태그

        ul 태그와 함께 목록을 생성해주는 태그
        ul 태그와 함께 목록을 생성해주는 태그

    문단을 의미하는 태그
data = """
다음의 html 에서 태그를 제거해서 출력 예시와 같은 문자열을 만들어주세요.
<div>
    https://www.naver.com">클릭시 href 속성 값의 </a href="링크로 이동하는 태그</a>
    <img src="image.jpg">src 속성에 이미지를 브라우저에 나타내주는 태그</img>
    <ul>
        <li>ul 태그와 함께 목록을 생성해주는 태그</li>
        <li>ul 태그와 함께 목록을 생성해주는 태그</li>
    </ul>
    <p>문단을 의미하는 태그</p>
    <br memo="줄바꿈을 해주는 태그">
</div>
"""

pat = "<[^>]+>"
print(re.sub(pat,"",data))
 
다음의 html 에서 태그를 제거해서 출력 예시와 같은 문자열을 만들어주세요.

    클릭시 href 속성 값의 링크로 이동하는 태그
    src 속성에 이미지를 브라우저에 나타내주는 태그
    
        ul 태그와 함께 목록을 생성해주는 태그
        ul 태그와 함께 목록을 생성해주는 태그
    
    문단을 의미하는 태그
    


data = "나의 전화번호는 010-0000-0000 입니다. 너의 전화번호는 010-1111-1111 입니다."
re.findall("\d{3}-\d{4}-\d{4}",data)

['010-0000-0000', '010-1111-1111']
 
 
 
  • 프로그램 내에서 자주사용하는 정규식 패턴에 경우 re.complie 함수를 이용해서 컴파일을 미리하여 패턴객체를 생성해서 찾자.
  • 자주쓰는 패턴이라면 정규식을 미리 컴파일하자.
 
 
pat_obj.findall(data)

['010-0000-0000', '010-1111-1111']
 
반응형

댓글