Python에서 정규 표현식을 사용하여 날짜와 시간을 매칭하는 방법

Python에서 텍스트 데이터에서 날짜와 시간을 추출하기 위한 정규 표현식 사용법을 설명합니다. 정규 표현식은 패턴 매칭을 통해 특정 형식의 문자열을 효율적으로 탐지할 수 있는 강력한 도구입니다. 이 글에서는 정규 표현식의 기초부터 응용까지 다루며, Python에서 날짜와 시간을 정확하게 매칭하는 방법을 구체적인 예와 함께 소개합니다.

정규 표현식이란

정규 표현식(Regular Expression)은 문자열의 패턴을 지정하기 위한 특수한 문자열입니다. 특정 문자의 조합이나 반복 등을 표현하고, 문자열 검색, 치환, 추출 등에 사용됩니다. 프로그래밍과 텍스트 처리 분야에서 널리 사용되며, 효율적이고 유연하게 데이터를 처리하는 강력한 도구입니다.

Python의 정규 표현식 모듈

Python에서는 정규 표현식을 다루기 위한 표준 라이브러리로 “re” 모듈이 제공됩니다. 이 모듈을 사용하면 문자열 검색, 치환, 분할, 매칭 등의 작업을 쉽게 수행할 수 있습니다. 아래에 기본적인 사용법과 주요 함수를 소개합니다.

기본적인 사용법

정규 표현식을 사용하려면 먼저 “re” 모듈을 임포트합니다. 그리고 정규 표현식 패턴을 생성하여 이를 사용해 문자열 작업을 수행합니다.

import re

# 정규 표현식 패턴을 컴파일
pattern = re.compile(r'\d{4}-\d{2}-\d{2}')

# 매칭을 수행
match = pattern.match('2023-06-16')
if match:
    print("매칭되었습니다:", match.group())

주요 함수들

  • re.match(): 문자열의 시작이 패턴과 일치하는지 확인합니다.
  • re.search(): 전체 문자열을 검색하여 첫 번째 매칭을 반환합니다.
  • re.findall(): 패턴과 일치하는 모든 부분 문자열을 리스트로 반환합니다.
  • re.sub(): 패턴과 일치하는 부분 문자열을 치환합니다.

날짜 매칭 방법

날짜를 매칭하는 정규 표현식은 날짜 형식에 따라 다릅니다. 여기에서는 일반적인 날짜 형식인 “YYYY-MM-DD”를 예로 들어 설명합니다. 이 형식은 연도(4자리), 월(2자리), 일(2자리)로 구성됩니다.

기본적인 날짜 매칭

다음의 정규 표현식 패턴은 “YYYY-MM-DD” 형식의 날짜를 매칭합니다.

import re

# 정규 표현식 패턴을 생성
date_pattern = re.compile(r'\b\d{4}-\d{2}-\d{2}\b')

# 샘플 텍스트
text = "오늘의 날짜는2023-06-16입니다."

# 매칭을 수행
matches = date_pattern.findall(text)
if matches:
    print("발견된 날짜:", matches)
else:
    print("날짜를 찾을 수 없습니다.")

이 패턴은 4자리 숫자(\d{4}) 뒤에 하이픈(-), 2자리 숫자(\d{2}), 다시 하이픈, 그리고 2자리 숫자(\d{2})를 매칭합니다. \b는 단어 경계를 나타내며, 날짜 전후에 다른 문자가 없음을 보장합니다.

응용 예시: 여러 날짜 형식 매칭

여러 가지 날짜 형식을 매칭하려면 여러 패턴을 결합할 수 있습니다. 예를 들어 “YYYY/MM/DD” 또는 “YYYY.MM.DD” 형식을 포함하여 매칭하려면 아래와 같이 합니다.

# 여러 패턴을 결합한 정규 표현식
date_pattern = re.compile(r'\b\d{4}[-/\.]\d{2}[-/\.]\d{2}\b')

# 샘플 텍스트
text = "오늘의 날짜는2023-06-16, 어제는2023/06/15, 내일은2023.06.17입니다."

# 매칭을 수행
matches = date_pattern.findall(text)
if matches:
    print("발견된 날짜:", matches)
else:
    print("날짜를 찾을 수 없습니다.")

이 패턴은 하이픈(-), 슬래시(/), 점(.) 중 하나를 구분자로 인식합니다.

시간 매칭 방법

시간을 매칭하는 정규 표현식도 시간 형식에 따라 다릅니다. 여기에서는 일반적인 시간 형식인 “HH:MM:SS”를 예로 들어 설명합니다. 이 형식은 시(2자리), 분(2자리), 초(2자리)로 구성됩니다.

기본적인 시간 매칭

다음의 정규 표현식 패턴은 “HH:MM:SS” 형식의 시간을 매칭합니다.

import re

# 정규 표현식 패턴을 생성
time_pattern = re.compile(r'\b\d{2}:\d{2}:\d{2}\b')

# 샘플 텍스트
text = "현재 시간은14:30:45입니다."

# 매칭을 수행
matches = time_pattern.findall(text)
if matches:
    print("발견된 시간:", matches)
else:
    print("시간을 찾을 수 없습니다.")

이 패턴은 2자리 숫자(\d{2}) 뒤에 콜론(:), 다시 2자리 숫자, 콜론, 그리고 2자리 숫자를 매칭합니다. \b는 단어 경계를 나타내며, 시간 전후에 다른 문자가 없음을 보장합니다.

응용 예시: 24시간제 및 12시간제 시간 매칭

24시간제와 12시간제 시간을 매칭하려면 오전/오후 표기를 포함하여 패턴을 확장해야 합니다.

# 24시간제 및 12시간제 시간 패턴
time_pattern = re.compile(r'\b((1[0-2]|0?[1-9]):[0-5][0-9](\s?[APap][Mm])?|([01][0-9]|2[0-3]):[0-5][0-9])\b')

# 샘플 텍스트
text = "현재 시간은14:30, 오전 미팅은10:00 AM, 오후 미팅은02:00 PM입니다."

# 매칭을 수행
matches = time_pattern.findall(text)
if matches:
    print("발견된 시간:", [match[0] for match in matches])
else:
    print("시간을 찾을 수 없습니다.")

이 패턴은 다음 형식의 시간을 인식합니다.

  • 24시간제 시간(예: 14:30)
  • 12시간제 시간(예: 10:00 AM, 02:00 PM)

응용 예시: 날짜와 시간의 포맷 변환

정규 표현식을 사용하여 날짜와 시간을 추출하고 다른 포맷으로 변환하는 방법을 소개합니다. 여기서는 “YYYY-MM-DD HH:MM:SS” 형식의 날짜와 시간을 “MM/DD/YYYY hh:mm AM/PM” 형식으로 변환하는 예를 보여줍니다.

날짜와 시간 추출

먼저 날짜와 시간이 포함된 텍스트에서 정규 표현식을 사용하여 해당 부분을 추출합니다.

import re

# 정규 표현식 패턴을 생성
datetime_pattern = re.compile(r'(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})')

# 샘플 텍스트
text = "이벤트는2023-06-16 14:30:45에 시작합니다."

# 매칭을 수행
match = datetime_pattern.search(text)
if match:
    year, month, day, hour, minute, second = match.groups()
    print("추출된 날짜와 시간:", match.group())
else:
    print("날짜와 시간이 없습니다.")

포맷 변환 구현

추출한 날짜와 시간을 “MM/DD/YYYY hh:mm AM/PM” 형식으로 변환합니다.

# AM/PM 판별
hour = int(hour)
if hour >= 12:
    period = "PM"
    if hour > 12:
        hour -= 12
else:
    period = "AM"
    if hour == 0:
        hour = 12

# 새로운 포맷으로 변환
formatted_datetime = f"{month}/{day}/{year} {hour:02}:{minute} {period}"
print("변환된 날짜와 시간:", formatted_datetime)

이 코드는 24시간제 시간을 12시간제로 변환하고 AM/PM을 붙여 새로운 포맷으로 정리합니다.

연습 문제: 날짜와 시간 추출

정규 표현식을 사용한 날짜와 시간 추출에 대해 이해를 깊이기 위해 아래 연습 문제를 풀어보세요. 이 문제들을 통해 실제로 손을 움직이며 스킬을 습득해 보세요.

연습 문제1: 단일 날짜 추출

다음 텍스트에서 “YYYY-MM-DD” 형식의 날짜를 추출하는 정규 표현식을 작성해 보세요.

text = "마감일은2024-07-20입니다. 프로젝트 시작일은2024-06-01이었습니다."

답안 예시

import re

date_pattern = re.compile(r'\b\d{4}-\d{2}-\d{2}\b')
dates = date_pattern.findall(text)
print("추출된 날짜:", dates)

연습 문제2: 여러 시간 추출

다음 텍스트에서 “HH:MM:SS” 형식의 시간을 모두 추출하는 정규 표현식을 작성해 보세요.

text = "아침 식사는07:30:00, 점심은12:00:00, 저녁은19:45:00에 예정되어 있습니다."

답안 예시

import re

time_pattern = re.compile(r'\b\d{2}:\d{2}:\d{2}\b')
times = time_pattern.findall(text)
print("추출된 시간:", times)

연습 문제3: 날짜와 시간 추출 및 포맷 변환

다음 텍스트에서 “YYYY-MM-DD HH:MM:SS” 형식의 날짜와 시간을 추출하고 “MM/DD/YYYY hh:mm AM/PM” 형식으로 변환하세요.

text = "미팅은2024-06-16 14:30:45에 시작됩니다."

답안 예시

import re

# 정규 표현식 패턴을 생성
datetime_pattern = re.compile(r'(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})')

# 매칭을 수행
match = datetime_pattern.search(text)
if match:
    year, month, day, hour, minute, second = match.groups()

    # AM/PM 판별
    hour = int(hour)
    if hour >= 12:
        period = "PM"
        if hour > 12:
            hour -= 12
    else:
        period = "AM"
        if hour == 0:
            hour = 12

    # 새로운 포맷으로 변환
    formatted_datetime = f"{month}/{day}/{year} {hour:02}:{minute} {period}"
    print("변환된 날짜와 시간:", formatted_datetime)
else:
    print("날짜와 시간이 없습니다.")

자주 발생하는 오류와 그 해결 방법

정규 표현식을 사용할 때 몇 가지 자주 발생하는 오류를 만날 수 있습니다. 이러한 오류를 이해하고 적절히 대처하면 정규 표현식의 정확도와 효율성을 향상시킬 수 있습니다.

오류1: 탐욕적 매칭으로 인한 과도한 일치

탐욕적 매칭(greedy matching)은 가능한 한 긴 문자열을 일치시키려고 합니다. 이로 인해 예상치 못한 부분까지 매칭될 수 있습니다.

해결 방법: 비탐욕적 매칭 사용

비탐욕적 매칭(lazy matching)을 사용하여 필요한 최소한의 부분만 매칭시킬 수 있습니다. *?+?처럼 물음표를 추가하여 비탐욕적으로 만듭니다.

import re

text = "Start123End456End"
pattern = re.compile(r'Start.*?End')

matches = pattern.findall(text)
print("비탐욕적 매칭 결과:", matches)

오류2: 이스케이프 문자 오용

정규 표현식에서 특별한 의미를 갖는 문자(예: .* 등)를 그대로 사용하면 의도한 대로 매칭되지 않을 수 있습니다.

해결 방법: 이스케이프 문자를 올바르게 사용

특별한 문자를 그대로 사용하려면 백슬래시(\)를 사용하여 이스케이프해야 합니다.

import re

text = "파일 이름은example.txt입니다."
pattern = re.compile(r'example\.txt')

matches = pattern.findall(text)
print("이스케이프 문자 사용 결과:", matches)

오류3: 패턴 복잡성으로 인한 성능 저하

복잡한 정규 표현식 패턴은 성능이 저하되고 실행 시간이 길어질 수 있습니다.

해결 방법: 패턴 최적화

정규 표현식 패턴을 간결하고 효율적으로 설계하면 성능을 향상시킬 수 있습니다. 또한 불필요한 캡처 그룹을 피하고 필요한 최소한의 매칭을 목표로 합니다.

import re

# 복잡한 패턴
complex_pattern = re.compile(r'(\d{1,4})-?(\d{1,2})-?(\d{1,2})')

# 간단하고 효율적인 패턴
optimized_pattern = re.compile(r'\d{1,4}-\d{1,2}-\d{1,2}')

오류4: 매칭 결과 오해

정규 표현식의 매칭 결과를 정확히 이해하지 못하면 의도하지 않은 결과를 얻을 수 있습니다.

해결 방법: 매칭 객체 사용

매칭 객체를 사용하여 매칭된 부분 문자열이나 캡처 그룹을 정확하게 얻습니다.

import re

text = "오늘의 날짜는2024-07-20입니다."
pattern = re.compile(r'(\d{4})-(\d{2})-(\d{2})')

match = pattern.search(text)
if match:
    year, month, day = match.groups()
    print(f"추출된 날짜: 연={year}, 월={month}, 일={day}")
else:
    print("날짜를 찾을 수 없습니다.")

정리

정규 표현식은 날짜나 시간처럼 특정 형식의 문자열을 효율적으로 매칭하기 위한 강력한 도구입니다. Python의 “re” 모듈을 사용하면 복잡한 문자열 작업을 쉽게 수행할 수 있습니다. 이 글에서는 기본적인 정규 표현식 사용법부터 날짜와 시간의 구체적인 매칭 방법, 응용 예시와 연습 문제, 자주 발생하는 오류와 그 해결 방법까지 소개했습니다. 정규 표현식을 적절하게 활용하면 데이터 처리의 정확도와 효율성을 크게 향상시킬 수 있습니다.