📢 개요

정규표현식(Regular Expressions) : 복잡한 문자열을 처리할 때 사용하는 도구

  • 특정 프로그래밍 언어에 종속된 문법을 가진 것이 아니라, 문자열을 처리하는 곳이라면 폭넓게 사용 가능
  • 파이썬의 기본 모듈 중 re 모듈이 정규표현식을 지원

👇 왜 배워야 할까 ?

더보기

다음과 같은 문제가 주어졌다고 생각해보자.
[ 보안을 위해 고객 정보 중 전화번호 가운데 자리의 숫자는 * 문자로 변경하세요. ]

고객 정보는 이름, 주민번호, 전화번호가 문자열 데이터로 주어진다고 가정해봅시다.

text = '''
Elice 123456-1234567 010-1234-5678
Cheshire 345678-678901 01098765432
'''

이 문제를 정규식을 사용하지 않고 풀려면 매우 복잡하게 풀어야 합니다.

  1. 전체 텍스트를 공백 문자를 기준으로 나눈다.
  2. 나누어진 문자열이 전화번호 형식인지 점검한다.
  3. 전화번호를 다시 나누어 가운데 자리의 숫자를 *로 변환한다.
  4. 나눈 문자열을 다시 합쳐 전화번호를 완성한다.

그런데 나누어진 문자열을 전화번호 형식인지 어떻게 점검할까요? 그리고 가운데 자리의 숫자는 어떻게 나누어 *로 변환하고 다시 합칠까요?

설상가상으로 전화번호의 구분문자인 -도 있기 때문에 문제 해결은 더욱 쉽지 않습니다.
그러나 정규표현식을 이용하면 매우 간편하게 코드를 작성할 수 있습니다.

앞서 예로 든 전화번호같이, 원하는 형식의 문자열을 검색할 때 메타문자와 수량자 등 다양한 패턴을 사용하여 매치하고, 그룹핑을 이용하여 원하는 부분만 골라내고 re모듈의 메서드로 문자열을 수정할 수도 있습니다.

 

📢 re 모듈

import re	
 

re — Regular expression operations — Python 3.9.1 documentation

This module provides regular expression matching operations similar to those found in Perl. Both patterns and strings to be searched can be Unicode strings (str) as well as 8-bit strings (bytes). However, Unicode strings and 8-bit strings cannot be mixed:

docs.python.org

 

📢 정규식 검사 함수

문자열에 대해 정규식으로 검사하는 함수는 대표적으로 4가지가 있다.

함수 이름 기능
re.match(pattern, string) string 시작 부분부터 패턴이 존재하는지 검사하여 MatchObject를 반환함.
re.search(pattern, string) string 전체에서 pattern이 존재하는지 검사하여 MatchObject를 반환함.
re.findall(pattern, string) string 전체에서 패턴과 매치되는 모든 경우를 찾아 list로 반환함.
re.finditer(pattern, string) string 전체에서 패턴과 일치하는 결과에 대한 iterater 객체를 반환함.

 

📢 문자열 수정 함수

re 모듈에는 패턴과 매치된 무자열을 찾아줄 뿐만 아니라, 편집할 수 있는 함수들도 존재한다.

함수 이름 기능
re.sub(pattern, repl, string) string 에서 pattern과 매칭되는 부분을 repl로 수정한 문자열을 반환함.
re.subn(pattern, repl, string) re.sub()과 동일하지만, 함수의 결과를 (결과 문자열, 교체 횟수)꼴의 튜플로 반환함.

 

📢 메타 문자

메타 문자특정한 문자 혹은 계열을 표현하는 약속된 "기호" 이다.
메타 문자를 이용하면 특정한 규칙을 가진 여러 단어를 짧게 압출할 수 있어 편리하다.

주요 메타문자

  • [^ ] 와 같이 문자클래스 [ ] 안에 ^이 쓰이면, 문자열의 시작이 아닌, not 에 의미로 사용
  • [ - ]문자클래스 [ ] 안에 - 를 기준으로, 왼쪽 오른쪽에 범위로 쓸 문자를 쓰면, 그 사이에 범위에 해당하는 문자 전부를 의미한다. 반드시 왼쪽의 유니코드(또는 아스키코드)값이 오른쪽보다 작아야한다.
  • ★ "(?i)" = "(?i) 플래그" 라고 부른다. 특정 패턴 위치에 상관없이, 이 플래그를 넣어주면, 대소문자를 구분하지 않겠다는 의미

 

📢 수량자(Quantifier)

동일한 글자나 패턴이 반복될 때, 그대로 정규표현식을 만들고자 하면 상당히 불편하다.
\d 와 \w를 이용하면 각각 숫자와 문자를 "한 글자"씩 매칭해준다.
이는, 이어지는 문자를 패턴으로 만들어, "단어 단위"로 매칭해야 할 때 매우 불편하다.

이런 상황에서 유용한게 수량자(Quantifier) 이다.

주요 수량자(Quantifier)

  • ★ ? = "수량자 탐욕성 억제" 연산자

    표에, "0개 또는 1개"를 의미하는 수량연산자 ? 와는 다른 표현이다 !! (주의)
  • 수량자의 원래 특성은 "탐욕적"이라서, 매칭되는 "최대한 긴 문자열을 반환"하는데, 그게 아니라 가능한 "최소한"의 수량과 매칭하고 싶을 때 사용한다.

    ex) text = "<html><head><title>제목</head></html>" 일 때


    1. pattern = "<.*>" 일 때

    👉 ["<html><head><title>제목</head></html>"]  전체 하나가 반환 될것이다. <의 시작과 >의 맨끝을 기준

    2. pattern = <.*?>" 일 때 ( 수량자 탐욕 억제 사용 )

    👉 [ "<html>" , "<head>" , "<title>" , "</head>", "</html>" ] 반환. < >의 최소한의 기준으로 나눈다.

 

📢 그룹

( )그룹을 나타낸다. 그룹은 전체 패턴 내에서 "하나로 묶여지는 패턴"을 말한다.
그룹과 | 를 결합한 형태, 또는 그룹 뒤에 수량자를 붙이는 패턴으로 자주 사용된다.

예시

  • (e|a)lice  elice, alice와 매칭됩니다.
  • (tom|pot)ato는 tomato, potato와 매칭됩니다.
  • (base|kick){2}  basebase, basekick, kickkick, kickbase 와 매칭됩니다.

그룹 참조 예시

  • 특정문자열 = "(그룹1)쏼라쏼라~(그룹2)"  << 예시가 있다치자.
  • ★ 이 그룹을 "참조"할 때, "\g<그룹번호>" 를 사용하여, 내가 정의했던, 정규식의 그룹을 참조할 수 있다.

그룹의 재사용

한 번 만든 그룹은 재사용할 수도 있습니다. 만들어진 순서부터 1번부터 시작하는 그룹으로 참조할 수 있는데, 매치한 그룹을 패턴 내에서 재사용하려면 \\1과 같이 그룹 번호를 이스케이프하여 나타내야 합니다.

예시

  • (to)ma\\1은 tomato와 매칭됩니다. 괄호를 사용하여 앞에서 만든 그룹 (to)를 뒤에서 재사용하는 모습입니다.

외 ( group( ) 메소드 )

이외에도 그룹에는 re 모듈의 match 객체에 속해있는 group 메서드를 이용하여 매칭된 결과 중 일부 내용만을 추출할 수 있는 등 다양한 사용법이 있습니다.

text = "목표텍스트"
pattern = "정규표현식"
match_object = re.search(pattern, text)		# 매칭된 "객체"를 반환
match_object.group()	# 매칭된 객체 기반으로, 그루핑

 

📢 비캡쳐링그룹

예를들어, "tomato potato" 라는 문자열이 있다.  여기서, tomato 와 potato를 뽑아내기위해 앞선, "그룹"으로는"(tom|pot)ato"를 패턴으로 넣을 것이다. 

👉 그러나, 결과는 ["tom", "pot"] 으로 나올 것이다.

★ 이유는, 파이썬 정규표현식에서 그룹으로 "캡쳐" 한 부분이 있다면, "이외에 부분들은 출력하지 않기 때문"이다.
위 패턴에서는, "ato"는 그룹에 속해있지 않기 때문에, findall 함수에서 누락(해당되지 X)된 것이다.

해결법

👉 그룹 ( ) 앞에 ?: 을 붙인다.  ( ex. "(?:tom|pot)ato)" )

단, 비캡쳐링 그룹은 캡쳐가 되지 않는 그룹이기 때문에, "참조하여 사용할 수 없다."

비캡쳐링그룹은 패턴 문자들을 묶되, 그룹 단위로 매칭되지는 않게끔 한다.
그룹으로 묶은 것들을 "최종 결과"에서 따로 구분하여 사용하지 않는 경우에 적용한다.
 

 

📝 Reference : Elice Academy

728x90
반응형

+ Recent posts