파이썬 정규표현식 (re 모듈): match, search, findall, replace 특수문자 패턴 예제
이번 포스팅은 파이썬 정규표현식 모듈인 re
모듈에 대해서 쉽게 풀어쓴 해설지입니다.
언제나 가장 좋은 자습서는 파이썬 공식 문서입니다.
이 글을 통해, 방향을 잡고나서 해당하는 공식 문서를 읽어나가시면, 내용이 머릿 속에 들어오는 경험을 할 수 있을 것입니다. 그럼 시작할게요!
1. 정규표현식이란?
일반적으로 Regex, 한국어로는 정규식 또는 re 라고 불리는 정규표현식은, 정해진 기호들을 가지고 검색 패턴을 정의하는 방법입니다. 정규식을 사용하면 텍스트 패턴을 매우 유연하고 빠르게 조작하고 찾아낼 수 있기 때문에, 모든 프로그래머가 갖춰야 할 강력한 도구입니다.
파이썬에 내장된 re
모듈은 정규표현식으로 작업할 수 있는 강력하고 효율적인 방법을 제공합니다.
내장 모듈이기 때문에, 따로 설치하지 않고도 아래와 같이 import
해서 사용가능합니다.
import re
2. 정규표현식 기호 목록
파이썬 정규식은 원시 문자열을 사용한 r"[정규식_패턴]
의 형태를 가집니다.
예를 들어, "파이썬"
이라는 문자로 시작하는 모든 문자열을 찾아내기 위해서는 r"^파이썬"
이라는 정규식 패턴을 사용할 수 있습니다.
다음은 정규식 패턴을 정의할 때 사용하는 기초적인 정규식 기호입니다. 기억하기 쉽게 몇 가지 카테고리로 분류해보았습니다.
.
: 모든 문자를 의미합니다 (개행 제외).
2.1.문자열의 시작과 끝 (Boundary anchors)
^
: 문자열의 시작 부분을 의미합니다.$
: 문자열의 끝을 의미합니다.
2.2. 문자열 개수 (Quantifiers)
?
: 앞의 문자가 없거나 1개 있는 경우를 의미합니다.*
: 앞의 문자가 없거나 하나 이상 있는 경우를 의미합니다.+
: 앞의 문자를 하나 이상 있는 경우를 의미합니다.{n}
: 앞의 문자가 정확히 n번 나타나는 경우를 의미합니다.{n,}
: 앞의 문자가 n개 이상 나타나는 경우를 의미합니다.{n,m}
: 앞의 문자가 n개에서 m개 사이로 나타나는 경우를 의미합니다.
2.3. 문자열 형식 (Character classed and sets)
\d
: 모든 숫자를 의미합니다.\D
: 숫자를 제외한 모든 문자를 의미합니다.\s
: 스페이스, \t, \n, \r, \f, \v 로 만들어지는 모든 공백을 의미합니다.\S
: 공백이 아님을 의미합니다.\w
: 모든 알파벳과 숫자, _ 를 의미합니다.\W
: 알파벻과 숫자, _를 제외한 모든 문자를 의미합니다..
: \n 를 제회한 모든 문자를 의미합니다.[]
: 대괄호 안에 속한 모든 문자를 의미합니다.
2.4. 논리 연산자 (Logical operators)
(abc)
: 중괄호 안에 있는 문자 그룹이 그대로 나타나는 경우를 의미하는 그룹 연산자입니다.[^abc]
: 대괄호 안의 문자가 아닌 모든 문자가 나타나는 경우를 의미하는 여집합 연산자입니다.(A|B)
: A 또는 B가 나타나는 경우를 의미하는 OR 연산자입니다.
3. re 모듈 함수 기초
파이썬 re
모듈은 정규 표현식으로 작업할 수 있는 여러 함수를 제공합니다. 가장 일반적으로 사용하는 함수는 다음과 같습니다.
함수를 사용하는 패턴은 섹션 4의 예제를 통해 살펴보겠습니다.
re.match()
: 문자열의 시작 부분에 정규식 패턴이 일치하는지 확인합니다.
import re
pattern = r"Hello"
text = "Hello, World!"
match = re.match(pattern, text)
if match:
print("Match found!")
else:
print("No match found.")
# Output: Match found!
re.search()
: 문자열 전체에서 정규식 패턴과 일치하는 항목이 있는지 확인합니다.
import re
pattern = r"World"
text = "Hello, World!"
search = re.search(pattern, text)
if search:
print("Match found!")
else:
print("No match found.")
# Output: Match found!
re.findall()
: 문자열에서 서로 겹치지 않는 모든 정규식 패턴을 문자열 리스트로 반환합니다.
import re
pattern = r"\d+"
text = "I have 3 apples and 5 oranges."
matches = re.findall(pattern, text)
print(matches)
# Output: ['3', '5']
re.finditer()
: 문자열에서 서로 겹치지 않는 모든 정규식 패턴을 yield 하는 Iterator 를 반환합니다.
import re
pattern = r"\d+"
text = "I have 3 apples and 5 oranges."
matches_iter = re.finditer(pattern, text)
for match in matches_iter:
print(match.group(), end=" ")
# Output: 3 5
re.sub()
: 문자열에서 정규식 패턴과 일치하는 모든 항목을 지정한 대체 문자열로 교체합니다.
import re
pattern = r"apple"
text = "I have an apple. It is a delicious apple."
new_text = re.sub(pattern, "orange", text)
print(new_text)
# Output: I have an orange. It is a delicious orange.
re.split()
: 문자열을 정규식 패턴의 발생 횟수에 따라 분할합니다.
import re
pattern = r"\s+"
text = "Hello World! How are you?"
substrings = re.split(pattern, text)
print(substrings)
# Output: ['Hello', 'World!', 'How', 'are', 'you?']
4. re 모듈 함수 예제
re
모듈 함수들이 눈에 익었다면, 이제 이 함수들을 사용한 몇 가지 실용적인 예제를 살펴봅시다:
예제 1: 텍스트에서 모든 이메일 주소 찾기
다양한 이메일 주소가 포함된 텍스트가 있고 이를 모두 추출하고 싶다고 가정해 보겠습니다.
re.findall(
) 함수를 사용하여 이를 수행하는 방법은 다음과 같습니다:
import re
text = "Contact us at info@example.com or support@example.org for any inquiries."
email_pattern = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
emails = re.findall(email_pattern, text)
print(emails) # Output: ['info@example.com', 'support@example.org']
예제 2: 텍스트의 URL을 대체 문자열로 바꾸기
여러 URL이 포함된 텍스트가 있고 이를 [URL]
과 같은 대체 문자열로 바꾸고 싶다고 가정해 봅시다.
이 작업에는 re.sub()
함수를 사용할 수 있습니다:
import re
text = "Visit our website at https://example.com and check our blog at https://blog.example.com."
url_pattern = r"https?://[^\s]+"
replaced_text = re.sub(url_pattern, "[URL]", text)
print(replaced_text) # Output: Visit our website at [URL] and check our blog at [URL].
예제 3: 다양한 형식의 전화번호 추출하기
다양한 형식의 텍스트에서 re.finditer()
함수를 이용해 전화번호를 추출해보겠습니다.
import re
text = "Call John at (123) 456-7890 or reach Jane at 987-654-3210 for more information."
phone_pattern = r"\(?\d{3}\)?[-\s]?\d{3}[-\s]?\d{4}"
phone_numbers = [match.group() for match in re.finditer(phone_pattern, text)]
print(phone_numbers) # Output: ['(123) 456-7890', '987-654-3210']
예제 4: 비밀번호 검증하기
이 예제에서는, 사용자가 입력한 비밀번호가 대문자 1개 이상, 소문자 1개 이상, 숫자 1개 이상, 총 글자 8자 이상 등의 기준을 충족하는지 확인합니다.
이 작업에는 re.search()
를 사용합니다.
import re
def is_valid_password(password):
if len(password) < 8:
return False
if not re.search(r"[A-Z]", password):
return False
if not re.search(r"[a-z]", password):
return False
if not re.search(r"\d", password):
return False
return True
password = "P4ssw0rd!"
print(is_valid_password(password)) # Output: True
예제 5: 여러 가지 기호를 기준으로 문자열 자르기
이 예제에서는 re.split()
함수를 사용하여 여러 구분 기호(쉼표, 세미콜론, 파이프)를 사용하여 문자열을 분할하겠습니다:
import re
text = "apple,banana;orange|grape"
delimiter_pattern = r"[,;|]"
fruits = re.split(delimiter_pattern, text)
print(fruits) # Output: ['apple', 'banana', 'orange', 'grape']
5. 한 걸음 더 나아가기
정규식 기초 문법과 함수 외에도 정규식에 대해 깊이 공부할 만 한 주제들이 있습니다.
- Lookahead 와 lookbehind assertion: 특정 정규식 패턴에 추가적인 패턴을 등록하는 방법입니다.
- Named groups 과 backreferences: 정규식에서 자료구조, 변수와 비슷한 테크닉을 사용하는 방법입니다.
- Non-capturing groups: group 을 사용할 때, 패턴 검색에는 사용하지만 그 값은 무시하는 테크닉입니다.
그 외에도 케이스에 상관없이 검색하는 방법, 여러 줄 모드 등 더 유용한 기법들을 함께 알아보세요.
6. re 모듈을 사용하는 팁
다음은 정규 표현식으로 작업할 때 더 쉽게 사용할 수 있는 몇 가지 팁과 요령입니다:
- 정규식 패턴에 원시 문자열(
r""
)을 사용하여 백슬래시를 이스케이프할 필요가 없도록 하세요. 파이썬에서 정규식을 위한 역슬래시를 사용하려면 이스케이프가 필요하지만 원시 문자열 (Raw string) 을 사용하면, 그럴 필요가 없습니다. - Regex101 은 정규식 패턴을 테스트하고 디버그할 수 있는 간편한 온라인 도구입니다. 한 번만 익혀두면 꾸준히 사용하게 될 것입니다.
- 복잡한 정규식 패턴을 하나로 만들면 가독성도 떨어지고 관리가 어렵습니다. 더 작고 관리하기 쉬운 단위로 나누어 가독성과 유지보수 가능성을 높입니다.
- 주석과 상세 모드(
re.VERBOSE
)를 사용하면 정규식 패턴을 더 이해하기 쉽게 만들 수 있습니다.re.compile()
과 함께 사용하여 상세한 주석을 추가할 수 있습니다.
7. 마치며
정규식은 파이썬에서 텍스트 조작과 패턴 검색을 위한 강력한 도구입니다.
re
모듈을 익히고 정규식 기초 문법을 이해하면, 다양한 텍스트 작업을 쉽게 처리할 수 있습니다.