본문 바로가기
AI

자연어처리 : 텍스트 전처리 : 정규표현식 정리

by 월곡동로봇팔 2020. 3. 4.

 

 

 

정규표현식, re 정리

 

1. compile

 
  • 문자 안에 특정 문자나 패턴이 존재하는지 여부를 알려줌.
  • 정규식객체 (re.RegexObject)를 return 하게 된다.
In [52]:
# 정규표현식 공부
import re
"""
# re.compile : 문자 안에 특정 문자나 패턴이 존재하는지 여부를 알려줌.
+ 정규식객체 (re.RegexObject)를 return 하게 된다.
"""
text = r"에러 1122 : 레퍼런스 오류\n 에러 1033: 아규먼트 오류"
regex = re.compile("에러 1122")
mo = regex.search(text)
if mo != None:
    print(mo.group())
else:
    print('단어가 없습니다.')
 
에러 1122
 
  • compile에서 정규식 표현을 이용, 특정 문자열 or 패턴을 검색
  • d는 digit을 의미, 0~9
In [53]:
text2 = r"문의사항이 있으면 032-232-3245 으로 연락주시기 바랍니다."
regex2 = re.compile(r'032-\d{3,4}-\d{4}')
# regex2 = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d)
regex_ex = re.compile(r'032-\d[0-9]+-\d[0-9]+')
print(regex2)
 
re.compile('032-\\d{3,4}-\\d{4}')
 
  • search 함수는 처음 매칭되는 단어만 return
  • findall 함수는 매칭되는 모든 경우를 return
In [54]:
mo2 = re.search(regex2, text2)
mo2.group()
# mo2 = regex2.search(text2)
mo_ex = re.search(regex_ex, text2)
print(mo_ex.group())
 
032-232-3245
 

compile 옵션

  • re.DOTALL : .이 줄바꿈 문자를 포함하여 모든 문자와 매치할 수 있도록 한다.
  • re.IGNORECASE or re.I : 문자를 대소문자 구별없이 검색할 때 쓰도록 한다.
  • re.MULTILINE or re.M : 해당 pattern을 각 줄에서 찾는다.
  • re.VERBOSE or re.X : 암호같은 정규식을 주석을 달아서 사용하게 \n은 컴파일할 때 제거된다.
 

re.DOTALL

In [55]:
p = re.compile('a.b')
m = p.match('a\nb')
print(m)

p = re.compile('a.b', re.DOTALL)
m = p.match('a\nb')
print(m)
 
None
<re.Match object; span=(0, 3), match='a\nb'>
 

re.IGNORECASE or re.I

In [56]:
p = re.compile('[a-z]+', re.I)
print(p.match('python'))
print(p.match('Python'))
print(p.match('PYTHON'))
 
<re.Match object; span=(0, 6), match='python'>
<re.Match object; span=(0, 6), match='Python'>
<re.Match object; span=(0, 6), match='PYTHON'>
 

re.MULTILINE or re.M

In [57]:
p = re.compile("^python\s\w+")

data = """python one
life is too short
python two
you need python
python three"""

print(p.findall(data))
 
['python one']
In [58]:
p = re.compile("^python\s\w+", re.MULTILINE)

data = """python one
life is too short
python two
you need python
python three"""

print(p.findall(data))
 
['python one', 'python two', 'python three']
 

re.VERBOSE or re.X

In [59]:
# charref = re.compile(r'&[#](0[0-7]+|[0-9]+|x[0-9a-fA-F]+);')

charref = re.compile(r"""
 &[#]                # Start of a numeric entity reference
 (
     0[0-7]+         # Octal form
   | [0-9]+          # Decimal form
   | x[0-9a-fA-F]+   # Hexadecimal form
 )
 ;                   # Trailing semicolon
""", re.VERBOSE)
 

2. 정규표현식의 기초, 메타 문자

 

[] 문자클래스

 
  • [] 는 문자 클래스를 말한다. 이 뜻은 '[]사이의 문자들과 매치'라는 의미를 가진다.
    ex) [abc] 는 a,b,c 중 한 개의 문자와 매치를 뜻한다.
    before 의 경우 b가있으니 match
    dude 의 경우 a,b,c 모두 없으니 match x

    • 는 두 문자 사이의 범위를 의미한다. 따라서 [0-5] == [012345] 이다.
 

Dot(.)

 
  • . Dot 는 \n 을 제외한 모든 문자와 매치됨을 의미한다.
  • ex) a.b 라고 쓰면 == "a + 모든문자 + b", 즉 a와 b라는 문자 사이에 어떤 문자가 들어와도 상관 없다.

cf) a[.]b 는 a와 b사이에 . 이라는 문자가 들어가야 한다. [] 안에는 무조건 문자클래스여서 모든 문자가 아니다.

 

반복 (* or +)

 
  • * 는 0번 반복부터 0번 이상 반복까지 모두 해당된다.
  • + 는 0번 반복은 제한 체 1번 반복부터 모두 해당된다.
  • * 은 포함해도 그만 안 포함해도 그만일 때 사용하고, + 는 무조건 한 번은 포함할 때 사용한다.
 

?

 
  • ? 는 있어도 되고 없어도 된다.
  • ex) ab?c 는 abc와 ac 둘다 가능.
 

{} 반복

 
  • ca{2,5}t == caat, caaat, caaaat, caaaaat 모두 가능.
  • * + ? 모두 {}이걸로 표현 가능하나 간결화된 표현이 좋다.
 

^, $ 옵션

 
  • ^ : 문자열의 처음을 의미한다. ex) ^python : 첫 단어는 무조건 python이어야 한다.
  • \$ : 문자열의 마지막을 의미한다. ex) python$ : 마지막 단어는 무조건 python이어야 한다.
 

3. 정규식을 이용한 문자열 검색

In [60]:
import re 
p = re.compile('[\w]+')
q = re.compile('[a-z]+')
 

match

 
  • match는 처음 input 한 값이 compile에 부합하는지를 보고 부합하는 부분을 출력해준다.
  • match는 첫 단어부터 조건에 부합하는 문장이 되야하는 강력한 조건일 때 쓰자.
In [61]:
m = q.match("python")
print(m)
n = q.match("3 python")
print(n)
 
<re.Match object; span=(0, 6), match='python'>
None
In [62]:
l = q.match("i like python")
print(l.group())
 
i
 
match의 method 종류
  • group() : 매치된 문자열을 돌려준다.
  • start() : 매치된 문자열의 시작 위치를 돌려준다.
  • end() : 매치된 문자열의 끝 위치를 돌려준다.
  • span() : 매치된 문자열의 (시작, 끝)을 튜플 형태로 돌려준다.
 

seacrh

 
  • search는 문자열 전체를 검색하기 때문에 match와 다르다.
  • search는 문장 전체에서 내가 원하는 단어 "하나"만 있을 때 뽑아쓰기 위해 좋다.
In [63]:
m2 = q.search("3 python good")
print(m2.group())
 
python
 

findall

 
  • findall은 search의 상위버젼이다.
  • 문장 내에서 조건에 부합하는 모든 단어를 다 뽑고싶을 떄 사용하자.
In [64]:
m3 = q.findall("3 python good")
print(m3)
 
['python', 'good']
 

finditer

 
  • finditer는 findall을 반복구문으로 돌릴수 있게 만든 method다.
  • finditer가 각각 뱉어내는 객체들은 match를 따른다.
In [65]:
result = q.finditer("life is too short")
print(result)
 
<callable_iterator object at 0x000002881EB97508>
In [66]:
for i in result:
    print(i, i.group())
 
<re.Match object; span=(0, 4), match='life'> life
<re.Match object; span=(5, 7), match='is'> is
<re.Match object; span=(8, 11), match='too'> too
<re.Match object; span=(12, 17), match='short'> short
 

4. 숫자로 indexing 하는 방법

 
  • 위에서 compile 했던 pattern으로 추출한 단어를 한 group으로 지어져 있다.
  • 따라서 group을 () 으로 나눠주면 group method를 이용해서 그룹을 분리할 수 있다.

  • group(0) : 문자열 전체

  • group(n) : 문자열 group n 번째 출력
In [67]:
import re
 
text = "문의사항이 있으면 032-232-3245 으로 연락주시기 바랍니다."
# regex2 = re.compile(r'032-\d{3,4}-\d{4}') -> () 가 없다.
regex = re.compile(r'(\d{3})-(\d{3}-\d{4})')
matchobj = regex.search(text)
areaCode = matchobj.group(1)
num = matchobj.group(2)
fullNum = matchobj.group()
print(num,areaCode) # 032 232-3245
 
232-3245 032
 

5. group 명으로 indexing 하는 방법

 
  • 숫자로 indexing 하는 경우 대신에 그룹이름을 지정할 수도 있다.
  • 이를 Named Capturing Group이라 한다.
In [68]:
import re
 
text = "문의사항이 있으면 032-232-3245 으로 연락주시기 바랍니다."
 
regex = re.compile(r'(?P<area>\d{3})-(?P<num>\d{3}-\d{4})')
matchobj = regex.search(text)
areaCode = matchobj.group("area")
num = matchobj.group("num")
print(areaCode, num)  # 032 232-3245
 
032 232-3245

댓글