정규 표현식(regular expression)

박현우·2021년 3월 31일
0

Python

목록 보기
1/1

정규 표현식이란

정규 표현식은 문자열로 이루어진 데이터의 가공에 쓰입니다.
알고리즘 문제를 보면 문자열을 가공하는 문제를 자주 볼 수 있습니다. 근데 문자열에 개행문자, 숫자, 알파벳, 특수문자 등등이 함께 포함되어있어 특정 문자열을 추출하거나 제거하려 할 때 일반적인 문자열 메소드만으로는 처리하기 어려운 경우가 발생합니다.

파이썬 뿐만 아니라, 다른 언어에서도 사용할 수 있고 쓰임새도 다양하여 알아두면 좋기 때문에 정규 표현식에 대한 포스팅을 하겠습니다.


먼저 간단하게 코드를 보며 알아보겠습니다.

import re

text = "as7df8s7g5sd"
a = re.compile("\d") # 1.
b = a.findall(text)  # 2.
print(b)

  • 정규 표현식은 re 혹은 regex 라는 모듈을 import하여 시작합니다.
  1. compile("정규표현식")

    • compile은 저희가 입력한 패턴을 정규식 객체로 리턴하는 메소드입니다.

    • compile 안에 들어가는 옵션은 다양합니다. 예를 들면, 숫자만 추출하고 싶거나, 마지막 글자가 "C"로 끝난다거나 다양한 경우를 패턴으로 입력할 수 있습니다.

    • 즉, a는 저희가 정한 패턴이라고 생각하면 됩니다.

  2. 패턴 메소드

    • a라는 패턴은 4가지의 검색 메소드를 가지고 있습니다.

패턴 메소드의 종류

Method기능
match(패턴, string)String의 처음부터 패턴을 검사합니다. 처음부분이 맞지 않으면 None을 리턴합니다.
search(패턴, string)String의 처음부터 패턴을 검사합니다. 패턴을 찾을때 까지 검사합니다.
findall(패턴, string)String의 처음부터 끝까지 일치하는 패턴을 모두 찾아 List로 반환합니다.
finditer(패턴, string)String의 처음부터 끝까지 일치하는 패턴을 모두 찾아 callable iterator로 리턴합니다.
  1. match
# 성공
p = re.compile("ab")
m = p.finditer("abbgaab")
print(m)

>> <re.Match object; span=(0, 2), match='ab'>

# 실패
p = re.compile("ab")
m = p.finditer("babbgaab")
print(m)

>> None

주어진 String이 패턴으로 시작하지 않으면 바로 None을 리턴합니다. 그리고 패턴으로 시작하면 Match object를 리턴합니다.

하지만 이 Match object를 어떻게 사용할까요?
바로 정보 추출 메소드를 사용해야합니다.

위 패턴 메소드에서 리스트를 반환하는 findall()을 제외하고 정보 추출 함수를 사용하여 알맞게 사용하시면 됩니다.


p = re.compile("ab")
m = p.match("abbgaab")
print(m.group()) # 매칭된 문자열을 반환합니다.
print(m.start()) # 매칭된 문자열의 시작 인덱스를 반환합니다.
print(m.end())   # 매칭된 문자열의 종료 인덱스를 반환합니다.
print(m.span())  # 시작과 종료 지점을 튜플로 반환합니다.
>> ab
>> 0
>> 2
>> (0, 2)

# 

  1. search
p = re.compile("ab")
m = p.search("agababc")
print(m.group())
print(m.start())
print(m.end())
print(m.span())
>> ab
>> 2
>> 4
>> (2, 4)

search도 match와 비슷하지만, 다른 점은 굳이 패턴으로 시작하지 않아도 String을 끝까지 탐색하여 일치하는 패턴을 찾고 인덱스를 추출해내거나 문자열을 얻어 낼 수 있습니다.


  1. findall()
p = re.compile("\d")
m = p.findall("a76dg78s6gs")
print(m)
>> ['7', '6', '7', '8', '6']

\d는 모든 숫자를 추출해내는 문자 클래스입니다. 문자열에서 입력한 패턴인 숫자만을 골라 리스트로 반환된 모습입니다.


  1. finditer()
p = re.compile("\d")
m = p.finditer("a76dg78s6gs")

for x in m:
    print(x.group())
    print(x.start())
    print(x.end())
    print(x.span())

>> 7
>> 1
>> 2
>> (1, 2)
>> 6
>> 2
>> 3
>> (2, 3)

모든 숫자를 추출한 뒤 iterator 객체에 담긴 m을 for문을 활용하여 사용할 수 있습니다. 이때, 요소 하나하나가 Match object이기 때문에 match()와 같이 group,start 등의 메소드를 사용하여 정보를 추출해야합니다.


메타 문자의 활용

앞서 활용한 예제는 숫자만 추출하거나, 특정 문자열을 추출하였습니다.
좀 더 디테일하게 활용하려면 메타 문자를 활용하여 옵션을 더 추가할 수 있습니다(ex 0~5까지만 추출, a로 시작해 b로 끝나는 문자열 추출 등등).
대표적으로 몇개만 알아보겠습니다.

Class의미
[][]안의 문자들을 매치
\d숫자만 매치, [0-9]와 같음
\D비숫자만 매치, [^0-9]와 같음
a*b*앞의 문자를 반복한 문자열을 매치, b ab aab 등이 매치됨.
a.ba와 b 사이에 문자가 끼어있으면 매치, acb aob 등이 매치됨.
a+ba와 b 사이에 문자가 끼어있으면 매치, 반드시 a가 하나이상 존재해야함.
a{2,3}a가 최소 2개 최대 3의 반복을 나타냄, a 불일치 aa 일치 aaaa 불일치.
\w숫자+문자를 매치.

예시

print(re.findall(r"a.b", "babababb"))
>> ['abb']

print(re.findall(r"[ab]", "babababb"))
>> ['b', 'a', 'b', 'a', 'b', 'a', 'b', 'b']

print(re.findall(r"ab", "babababb"))
>> ['ab', 'ab', 'ab']

print(re.findall(r"a*b", "abaaaababb"))
>> ['ab', 'aaaab', 'ab', 'b']

print(re.findall(r"a+b", "abaaaababb"))
>> ['ab', 'aaaab', 'ab']

print(re.findall(r"a|b", "babababb"))
>> ['b', 'a', 'b', 'a', 'b', 'a', 'b', 'b']

print(re.findall(r"ab{2,5}a", "aabbaabbbbaabbbbbbba"))
>> ['abba', 'abbbba']

print(re.findall(r"\w", "asg098%98(&&E&"))
>> ['a', 's', 'g', '0', '9', '8', '9', '8', 'E']

0개의 댓글