정규식표현 re

Leejaegun·2025년 4월 23일

Python & etc

목록 보기
24/27

re

re.sub는 Python의 re 모듈에서 제공하는 함수로, 정규 표현식을 사용하여 문자열에서 특정 패턴을 찾아 다른 문자열로 대체하는 기능을 합니다.

📌 기본 문법

import re

re.sub(pattern, repl, string, count=0, flags=0)

✅ 매개변수 설명
pattern: 정규 표현식 패턴 (찾을 문자열 패턴)
repl: 대체할 문자열 또는 함수
string: 원본 문자열
count (기본값: 0): 변경할 횟수 (0이면 모든 패턴 변경)
flags (기본값: 0): 정규식 플래그 (re.IGNORECASE, re.MULTILINE 등)
🔹 기본 사용 예제

import re

text = "Hello World! Hello Python!"
result = re.sub(r'Hello', 'Hi', text)
print(result)
# 출력: "Hi World! Hi Python!"

→ "Hello"를 "Hi"로 변경

🔹 정규 표현식 활용


text = "The price is $100."
result = re.sub(r'\$\d+', '[PRICE]', text)
print(result)

출력: "The price is [PRICE]."
→ $로 시작하는 숫자를 [PRICE]로 변경

🔹 count 사용 (변경 횟수 제한)

text = "apple, apple, banana, apple"
result = re.sub(r'apple', 'orange', text, count=2)
print(result)
# 출력: "orange, orange, banana, apple"

→ 앞에서 2개만 변경

🔹 repl에 함수 사용
대체 문자열 대신 함수를 사용하면, 매칭된 패턴을 동적으로 변경 가능

def replace_func(match):
    return match.group().upper()  # 대문자로 변경

text = "hello world! hello python!"
result = re.sub(r'hello', replace_func, text)
print(result)
# 출력: "HELLO world! HELLO python!"

→ "hello"를 "HELLO"로 변경

🔹 그룹 활용

text = "My number is 123-4567-890."
result = re.sub(r'(\d{3})-(\d{4})-(\d{3})', r'(\1) \2-\3', text)
print(result)
# 출력: "My number is (123) 4567-890."

→ 숫자 그룹을 "(123) 4567-890" 형태로 변환

🔹 플래그 활용 (re.IGNORECASE)

text = "Python is great. python is fun!"
result = re.sub(r'python', 'JavaScript', text, flags=re.IGNORECASE)
print(result)
# 출력: "JavaScript is great. JavaScript is fun!"

→ 대소문자 구분 없이 Python을 JavaScript로 변경

좋은 질문이야! \d\d+는 정규표현식(regular expression)에서 숫자를 의미하지만, 매칭 범위의 차이가 있어:

\d

  • 숫자 한 자리 (0~9) 하나만 매칭
  • 예: "a1b2"\d"1""2" 각각 따로 매칭

\d+

  • 숫자가 하나 이상 연속된 덩어리를 매칭
  • 예: "a123b45"\d+"123""45"덩어리로 매칭

🔍 re.sub("\d", repl, text) vs re.sub("\d+", repl, text) 차이

import re
text = "abc123def456"

re.sub("\d", "X", text)
# 결과: 'abcXXXdefXXX'  ← 숫자 하나하나를 X로 바꿈

re.sub("\d+", "X", text)
# 결과: 'abcXdefX'      ← 연속된 숫자 덩어리 하나를 X로 바꿈

요약

패턴의미예시 텍스트매칭 결과
\d숫자 1자리a12b31, 2, 3
\d+숫자 1자리 이상 (덩어리)a12b312, 3

✅ 1. re.search(pattern, string, flags=0)

💡 설명:

  • 문자열 전체 중에서 패턴이 처음으로 나타나는 부분을 찾음
  • 매칭되면 match 객체 반환, 아니면 None

✅ 예시:

import re
text = "The answer is <answer>42</answer>."

match = re.search(r"<answer>(.*?)</answer>", text)
print(match.group(1))  # 출력: 42

✅ 2. re.findall(pattern, string, flags=0)

💡 설명:

  • 문자열 전체에서 패턴에 일치하는 모든 부분을 리스트로 반환
  • 매칭된 문자열만 반환, 위치 정보는 없음

✅ 예시:

text = "I have <answer>42</answer> and <answer>7</answer>."

answers = re.findall(r"<answer>(.*?)</answer>", text)
print(answers)  # 출력: ['42', '7']

✅ 3. re.fullmatch(pattern, string, flags=0)

💡 설명:

  • 문자열 전체가 정규식 패턴과 정확히 일치할 때만 매칭
  • 문자열 일부만 일치하면 None 반환

✅ 예시:

text = "<answer>42</answer>"

# 전체 문자열이 정확히 이 형식이어야 함
match = re.fullmatch(r"<answer>\d+</answer>", text)
print(bool(match))  # 출력: True

match2 = re.fullmatch(r"<answer>\d+</answer>", "text <answer>42</answer>")
print(bool(match2))  # 출력: False

✅ 4. re.DOTALL

💡 설명:

  • 정규식 내의 .줄바꿈 문자(\n)까지 포함해서 모든 문자와 매치되도록 만드는 옵션 플래그

✅ 예시:

text = "<answer>\n42\n</answer>"

# .은 기본적으로 \n을 매치하지 않음
match1 = re.search(r"<answer>.*</answer>", text)
print(match1)  # None

# re.DOTALL 사용 시 줄바꿈도 포함해서 매치됨
match2 = re.search(r"<answer>.*</answer>", text, re.DOTALL)
print(match2.group())  # 출력: <answer>\n42\n</answer>

✅ 요약표

함수/옵션설명반환값
re.search()문자열 전체 중 첫 매치 반환match 객체
re.findall()문자열 전체에서 모든 매치된 문자열 반환문자열 리스트
re.fullmatch()전체 문자열이 패턴과 정확히 일치할 때만 매치match or None
re.DOTALL.이 줄바꿈까지 포함한 모든 문자 매치 가능하게 설정옵션 플래그

맞아! .group()re.search(), re.fullmatch(), re.match() 같은 함수의 결과로 나오는 match 객체에서 매칭된 문자열을 꺼낼 때 사용하는 메서드야.


.group() 핵심 요약

.group(n)의미
.group(0)전체 매치된 문자열 전체 반환
.group(1)첫 번째 괄호 ()로 감싼 그룹 반환
.group(2)두 번째 그룹 ...

✅ 예시 1: 기본 사용

import re

text = "The answer is <answer>42</answer>."
match = re.search(r"<answer>(.*?)</answer>", text)

if match:
    print(match.group(0))  # 전체 매치: <answer>42</answer>
    print(match.group(1))  # 그룹 1: 42

✅ 예시 2: 그룹이 여러 개일 때

text = "<answer>42</answer> on question <question>7</question>"
match = re.search(r"<answer>(\d+)</answer>.*<question>(\d+)</question>", text)

if match:
    print(match.group(0))  # 전체 매치
    print(match.group(1))  # 1번 그룹: answer 내용 (42)
    print(match.group(2))  # 2번 그룹: question 내용 (7)

✅ 예외 처리 주의

no_match = re.search(r"abc", "xyz")
print(no_match.group(0))  # ❌ AttributeError 발생 → match가 None이니까!

항상 .group()을 쓰기 전에 if match:로 체크하는 습관이 좋아 👍


✅ 요약

코드의미
.group(0)전체 매치 문자열
.group(1)첫 번째 괄호 안 캡처 그룹 내용
.group(2)두 번째 그룹 ...
profile
Lee_AA

0개의 댓글