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.llo | Hello 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*b | aaab | ['aaab'] |
+ | 1회 이상 반복 | a+b | aaab | ['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', '#'] |