본문 바로가기
C.W.K.
Stream
Lesson 09 of 10 · published

전방 탐색과 후방 탐색 결합

~8 min · combining, advanced

Level 0패턴 호기심
0 XP0/90 lessons0/15 achievements
0/100 XP to next level100 XP to go0% complete

앞뒤 조건을 함께 확인하고 가운데 값만 잡아

후방 탐색과 전방 탐색을 같은 매칭의 양쪽에 둘 수 있어. 두 조건은 경계를 확인할 뿐 소비하지 않아서 실제 결과에는 가운데 텍스트만 남아.

대괄호 사이의 값만 추출해 봐

(?<=\[)[^\]]+(?=\])
  • (?<=\[)는 바로 앞의 여는 대괄호를 확인하고
  • [^\]]+는 닫는 대괄호가 아닌 문자를 하나 이상 소비하고
  • (?=\])는 바로 뒤의 닫는 대괄호를 확인해.

[value]에 적용하면 매칭 결과는 value만 남아.

캡처 그룹으로도 같은 값을 꺼낼 수 있어

\[([^\]]+)\]로 전체 구간을 매칭한 다음 m.group(1)을 꺼내도 돼. 어느 방식이 더 낫다기보다 값의 경계를 패턴 결과에 직접 반영할지, 호출 코드에서 그룹을 꺼낼지의 차이야.

전후방 탐색이 잘 맞는 경우

  • findall에서 구분자를 제외한 문자열 목록을 바로 받고 싶을 때
  • ripgrep --pcre2처럼 전후방 탐색을 지원하는 검색·치환 도구에 같은 패턴을 쓸 때
  • 더 큰 패턴에서 캡처 번호를 추가하지 않고 경계만 확인하고 싶을 때

캡처 그룹이 더 나은 경우

  • Go나 RE2처럼 후방 탐색을 지원하지 않는 엔진을 사용할 때
  • 엔진이 허용하지 않는 가변 길이 앞 문맥을 다뤄야 할 때
  • 치환 과정에서 구분자를 포함한 전체 매칭과 안쪽 값을 모두 사용할 때

Code

양쪽 전후방 탐색과 캡처·python
import re

# Wrapped lookaround — 깨끗한 값
re.findall(r'(?<=\[)[^\]]+(?=\])', '[apple] [banana] [cherry]')
# ['apple', 'banana', 'cherry']

# 캡처 그룹 등가 — 튜플 또는 추가 unpacking
re.findall(r'\[([^\]]+)\]', '[apple] [banana] [cherry]')
# ['apple', 'banana', 'cherry']  — 그룹 한 개 findall 이 flatten 해서 같음

# 두 특정 마커 사이 단어
re.findall(r'(?<=ID:)\w+(?= accepted)', 'ID:abc123 accepted ID:def456 rejected')
# ['abc123']  — accepted 만

# 실전: 템플릿 변수명 추출
# {{username}} 또는 {{ user.name }} → 'username' 또는 'user.name'
re.findall(r'(?<=\{\{)\s*([\w.]+)\s*(?=\}\})', 'Hello {{ user.name }}, welcome {{username}}')
# ['user.name', 'username']  — lookaround 안 캡처 사용

External links

Exercise

{{name}}처럼 중괄호로 감싼 템플릿 자리표시자를 찾고 안쪽 이름만 반환하는 패턴을 작성해. Hi {{user}}, your order {{order_id}} is ready에 적용해서 ['user', 'order_id']가 나오는지 확인해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.