정규식 re.findall()에 대해

개발공부를해보자·2025년 5월 14일

공부 정리

목록 보기
25/34

관련 문제 프로그래머스 2018 KAKAO BLIND RECRUITMENT [1차] 다트게임

re.findall()에 대하여

# 🎯 정규표현식 re.findall() 개념 요약

# ✅ 사용된 정규식 패턴
pattern = r'(\d+)([SDT])([*#]?)'
# 의미: "숫자 + 보너스 문자(S/D/T) + 옵션기호(* 또는 # 또는 없음)" 구조를 그룹으로 추출

# ✅ 구성 요소 설명
# (1) \d+      → 숫자 하나 이상 (예: 1, 10, 3)
# (2) [SDT]    → 보너스 문자 중 하나
# (3) [*#]?    → * 또는 # 또는 없음 (옵션이 있을 수도 없을 수도 있음)
# 전체는 세 그룹으로 매칭되어 튜플로 추출됨

# ✅ 예시: "1S2D*3T" → re.findall 결과
# [('1', 'S', ''), ('2', 'D', '*'), ('3', 'T', '')]

# ✅ 주요 정규식 문법 요약
# \d     → digit 숫자 (0~9)
# +      → 앞의 항목이 1개 이상 반복
# []     → 대괄호 안에 있는 문자 중 하나와 매칭
# ?      → 앞의 항목이 0개 또는 1개 존재할 수 있음
# ()     → 그룹 지정 (findall 사용 시 튜플로 추출)

# ✅ 왜 정규식을 쓰는가?
# dartResult는 "1S2D*3T"처럼 공백 없이 연결되어 있음
# 단순 split이나 반복문보다 정규식이 구조 추출에 훨씬 효과적임

# ✅ 핵심 함수: re.findall()
# 문자열에서 pattern과 매칭되는 모든 부분을 리스트로 추출
# 각 매칭은 튜플 형태로 반환되어 이후 계산이 쉬움

# ✅ 전체 정규식 요약
# (\d+)         → 숫자 점수 (1자리든 2자리든)
# ([SDT])       → 제곱 보너스
# ([*#]?)       → 옵션 기호 (*, #, 또는 없음)

연습 문제

# 🔍 연습문제 1. 반환 결과는?
import re
pattern = r'(\d+)([SDT])([*#]?)'
re.findall(pattern, "1S2D*3T")

# 🔍 연습문제 2. 반환 결과는?
pattern = r'[SDT]'
re.findall(pattern, "1S2D*3T")

# 🔍 연습문제 3. 문자열 "10S#9D*8T"에서 [('10', 'S', '#'), ('9', 'D', '*'), ('8', 'T', '')]를 반환하기위한 정규식 작성하기

# 🔍 연습문제 4. 반환 결과는?
pattern = r'(\d+)([SDT])([*#])'
re.findall(pattern, "1S2D*3T#4S")

# 🔍 연습문제 5. 반환 결과는?
pattern = r'\d+[SDT][*#]?'
re.findall(pattern, "1S2D*3T")

정답과 해설

# 🔍 연습문제 1. 반환 결과는?
import re
pattern = r'(\d+)([SDT])([*#]?)'
re.findall(pattern, "1S2D*3T")
# 정답: [('1', 'S', ''), ('2', 'D', '*'), ('3', 'T', '')]
# 해설: 각 점수+보너스+옵션이 3개 튜플로 정확히 분리됨

# 🔍 연습문제 2. 반환 결과는?
pattern = r'[SDT]'
re.findall(pattern, "1S2D*3T")
# 정답: ['S', 'D', 'T']
# 해설: 정규식 [SDT]는 단순 문자 매칭으로 리스트 반환함

# 🔍 연습문제 3. 문자열 "10S#9D*8T"에서 [('10', 'S', '#'), ('9', 'D', '*'), ('8', 'T', '')]를 반환하기위한 정규식 작성하기
# 정답: re.findall(r'(\d+)([SDT])([#*]?)', "10S#9D*8T")

# 🔍 연습문제 4. 반환 결과는?
pattern = r'(\d+)([SDT])([*#])'
re.findall(pattern, "1S2D*3T#4S")
# 정답: [('2', 'D', '*'), ('3', 'T', '#')]
# 해설: 옵션이 반드시 있어야 하므로 빈 옵션은 제외됨

# 🔍 연습문제 5. 반환 결과는?
pattern = r'\d+[SDT][*#]?'
re.findall(pattern, "1S2D*3T")
# 정답: ['1S', '2D*', '3T']
# 해설: 그룹이 없으므로 문자열 단위로만 추출됨

# 5번만 틀렸다. 5번은 ['1', 'S', '', '2', 'D', '*', '3', 'T', '']로 예상했었음. 

findall() VS search() VS match()

  • 🔍 match는 "처음부터" 일치하는지 확인,
  • 🔍 search는 "어디든 처음 나오는" 하나만,
  • 🔍 findall은 "모두 추출"하여 리스트 반환함

import re
text = "abc123xyz456"

# match: 문자열 시작이 숫자여야 찾음 (여기선 실패)
print(re.match(r'\d+', text))        # None

# search: 문자열 전체 중 처음 숫자 찾음
m = re.search(r'\d+', text)
print(m.group())                     # '123'

# findall: 모든 숫자 패턴을 리스트로 추출
matches = re.findall(r'\d+', text)
print(matches)                       # ['123', '456']

주요 메타 문자

기호설명패턴테스트 문자열결과
.아무 문자 (개행 제외)H.lloHello Halo Hillo['Hello', 'Hillo']
\w단어 문자 [a-zA-Z0-9_]\w+Hi 123_world['Hi', '123_world']
\W단어 문자가 아닌 것\W+Hi 123_world![' ', '!']
\d숫자 [0-9]\d+Order 1234['1234']
\D숫자가 아닌 것\D+Order 1234['Order ']
\s공백 문자\s+Hi there![' ']
\S공백이 아닌 문자\S+Hi there!['Hi', 'there!']
*0회 이상 반복a*baaab['aaab']
+1회 이상 반복a+baaab['aaab']
?0회 또는 1회ab?a ab abb['a', 'ab']
{n}정확히 n회 반복a{3}aa aaaa['aaa']
[abc]a, b, 또는 c[abc]cat bat hat['c', 'a', 'b', 'a']
[^a-z]소문자가 아닌 것[^a-z]a1B#['1', 'B', '#']
profile
개발 공부하는 30대 비전공자 직장인

0개의 댓글