Data/Python

[Python] 파이썬 정규표현식 - 메타문자들, 그룹핑

재은초 2023. 6. 18. 11:58
반응형

메타 문자(Meta Characters)란?

  • 메타 문자란 원래 그 문자가 가진 뜻이 아닌 특별한 용도로 사용하는 문자를 말한다.
  • 만약 메타 문자가 아닌 문자 그 자체로 매치하고 싶은 경우에는 \^, \$ 와 같이 백슬래시 붙여서 사용
. ^ $ * + ? { } [ ] \ | ( )

[ ] 안에 있는 문자들과 매치

  • [ ] 안에는 어떤 문자나 메타 문자도 사용가능하며 해당 문자와 매치하는 문자를 반환
  • \d - 숫자와 매치, [0-9]와 동일한 표현식
  • \D - 숫자가 아닌 것과 매치, [^0-9]와 동일한 표현식
  • \s - 여백 문자와 매치, [ \t\n\r\f\v]와 동일한 표현식. 맨 앞의 빈 칸은 공백문자(space)를 의미.
  • \S - 여백 문자가 아닌 것과 매치, [^ \t\n\r\f\v]와 동일한 표현식.
  • \w - 문자+숫자와 매치, [a-zA-Z0-9_]와 동일한 표현식.
  • \W - 문자+숫자가 아닌 문자와 매치, [^a-zA-Z0-9_]와 동일한 표현식.
[abc]              # a, b, c 중 한 개의 문자와 매치

# [-] 두 문자 사이의 범위
[0-9]              # 숫자 0,1,2,3,4,5,6,7,8,9
[a-zA-Z]           # 알파벳 모두

# ^은 반대인 not을 의미
[^0-9]             # 숫자가 아닌 문자만 매치

. 모든 문자와 매치

  • 줄바꿈 문자인 \n을 제외한 모든 문자와 매치됨을 의미
a.b               # a와 b 문자 사이에 어떤 문자가 들어가도 모두 매치
                  # aab, a0b 매치

# 문자 .와 매치
a[.]b             # a와 b 문자 사이에 문자 .이 들어와야 매치
                  # a.b와 매치

 * 반복

  • 바로 앞에 있는 문자가 0부터 무한대로 반복될 수 있다는 의미
ca*t              # 문자 a가 0부터 무한대로 반복
                  # ct, cat, caaat 다 매칭

+ 반복

  • *가 0부터 반복이면 +는 1부터 반복
  • 바로 앞에 있는 문자가 1부터 무한대로 반복.
ca+t             # 문자 a가 1번 이상 반복
                 # cat, caaat 매치

{} 반복 횟수 지정

  • {m, n}  앞에 글자 반복 횟수 m부터 n까지로 지정.
{1,}               # 1회 반복부터인 +와 동일
{0,}               # 0회 반복부터인 *와 동일
{,3}               # 반복횟수 3회 이하

ca{2}t             # c + a 2번 반복 + t
                   # caat와 매치
                   
ca{2,5}t           # c + a 문자가 2~5회 반복 + t
                   # caat, caaaaat 매치

? 있거나 없거나

  • 앞에 문자가 있어도 되고 없어도 될 때, {0, 1} 와 같은 의미
ab?c            # a + b가 있거나 없거나 + c
                # abc, ac 매치

 

문자열 소비가 없는 메타문자

  • 위에 메타문자는 매치가 진행될 때 매치되고 있는 문자열의 위치가 변경(소비)
  • 아래 문자들은 열 소비가 없는(zerowidth assertions), 즉 위치가 변경되지 않는 메타 문자들

| 또는

  • or과 동일한 의미로 A|B라는 정규식이 있다면 A 또는 B라는 의미
>>> p = re.compile('Crow|Servo')
>>> m = p.match('CrowHello')
>>> print(m)
<re.Match object; span=(0, 4), match='Crow'>

^ 처음과 일치

  • 문자열의 맨 처음과 일치함을 의미
# 문자열이 처음인 경우 매치, 처음 아니면 매치되지 않음
>>> print(re.search('^Life', 'Life is too short'))
<re.Match object; span=(0, 4), match='Life'>

>>> print(re.search('^Life', 'My Life'))
None

$ 끝과 일치

  • ^ 메타 문자와 반대로, 문자열의 끝과 매치함
# 문자열이 마지막인 경우 매치, 마지막 아니면 매치되지 않음
>>> print(re.search('short$', 'Life is too short'))
<re.Match object; span=(12, 17), match='short'>

>>> print(re.search('short$', 'Life is too short, you need python'))
None

\A 처음과 일치

  • 문자열의 처음과 매치됨
  • ^ 메타 문자와 동일한 의미이지만 re.MULTILINE 옵션을 사용할 경우, ^은 각 줄의 문자열의 처음과 매치되지만 \A는 줄과 상관없이 전체 문자열의 처음하고만 매치된다.

\Z 끝과 일치

  • 문자열의 끝과 매치됨
  • re.MULTILINE 옵션을 사용할 경우 $ 메타 문자와는 달리 전체 문자열의 끝과 매치된다.

\b 단어 구분자

  • \b는 단어 구분자로, 보통 단어는 여백에 의해 구분된다.
  • \b는 원래 백스페이스(BackSpace)를 의미하므로 백스페이스가 아닌 단어 구분자임을 알려 주기 위해 r'\bclass\b'처럼 Raw string임을 알려주는 기호 r을 반드시 붙여 주어야 한다.
>>> p = re.compile(r'\bclass\b')      

# 여백 + class + 여백이므로 매치
>>> print(p.search('no class at all'))  
<re.Match object; span=(3, 8), match='class'>

# 여백으로 구분된 단어가 아니므로 매치안됨
>>> print(p.search('the declassified algorithm'))
None

>>> print(p.search('one subclass is'))
None

\B 여백 없을 때

  • \b 메타 문자와 반대의 경우로, whitespace로 구분된 단어가 아닌 경우에만 매치
>>> p = re.compile(r'\Bclass\B')

>>> print(p.search('the declassified algorithm'))
<re.Match object; span=(6, 11), match='class'>

# 단어의 앞뒤에 여백 하나라도 있으면 매치 안 됨 
>>> print(p.search('no class at all'))  
None

>>> print(p.search('one subclass is'))
None

() 그루핑

  • 그룹을 만들어주는 메타문자
>>> p = re.compile('(ABC)+')
>>> m = p.search('ABCABCABC OK?')
>>> print(m)
<re.Match object; span=(0, 9), match='ABCABCABC'>

>>> print(m.group())
ABCABCABC
# group() 메서드를 사용하여 그루핑된 부분의 문자열만 뽑기
>>> p = re.compile(r"(\w+)\s+(\d+[-]\d+[-]\d+)")
>>> m = p.search("park 010-1234-1234")

# m.group(n) n번째 그룹에 해당되는 문자열 반환
>>> print(m.group(0))          # 매치된 전체 문자열
park 010-1234-1234
>>> print(m.group(1))          # 첫번째 그룹
park
>>> print(m.group(2))          # 두번째 그룹
010-1234-1234

그루핑된 문자열 재참조(Backreferences)

  • 이미 지정된 그룹이 있고 해당 그룹을 참조하려면 재참조 메타문자인 \ 과 그룹 숫자를 적어주면 된다
# (그룹) + " " + 그룹과 동일한 단어
# \1 은 정규식 그룹 중 첫번째 그룹을 가르킴
>>> p = re.compile(r'(\b\w+)\s+\1')
>>> p.search('Paris in the the spring').group()
'the the'

그루핑된 문자열 이름 붙이기

  • (?P<그룹명>...) 로 그룹 이름 붙이기
  • 그룹명 재참조할 때에는 (?P=그룹이름)이라는 확장 구문을 사용
# 그룹명 붙이기 전
>>> p = re.compile(r"(\w+)\s+((\d+)[-]\d+[-]\d+)")

# 그룹명 붙인 후
>>> p = re.compile(r"(?P<name>\w+)\s+((\d+)[-]\d+[-]\d+)")
>>> m = p.search("park 010-1234-1234")
>>> print(m.group("name"))
park

# 그룹명으로 재참조
>>> p = re.compile(r'(?P<word>\b\w+)\s+(?P=word)')
>>> p.search('Paris in the the spring').group()
'the the'

 

Reference

반응형