본문 바로가기
C.W.K.
Stream
Lesson 02 of 12 · published

소유적 수량자 재방문

~6 min · possessive, quantifier

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

소유적 수량자와 원자 그룹은 같은 선택지를 없애

*+, ++, ?+, {n,m}+ 같은 소유적 수량자는 자신이 소비한 문자를 돌려주지 않아. 원자 그룹도 그룹 안에서 이미 성공한 선택으로 다시 들어가지 않아.

단일 수량자에서는 a++(?>a+)가 같은 효과를 내. 둘 다 a+가 잡은 문자를 뒤 패턴을 위해 내놓지 않지.

고정할 범위에 맞춰 문법을 골라

소유적 수량자\d++, \w*+처럼 수량자 하나의 소비량을 확정할 때 간결해.

원자 그룹(?>\d{3}-\d{4})처럼 여러 요소로 이루어진 구간 안의 백트래킹을 함께 막고 싶을 때 써.

지원 범위는 엔진마다 달라

엔진원자 그룹소유적 수량자
Python re 3.11+
Python regex
PCRE / PHP
Java
Ruby✓ (1.9+)
.NET
JavaScript
RE2/Go

문법이 없다면 경계를 더 분명하게 다시 써

JavaScript처럼 두 기능을 지원하지 않는 엔진에서는 모호한 분할 자체를 줄여야 해. 종료 표식이 한 글자라면 .+?X 대신 [^X]+X처럼 허용하지 않을 문자를 경계로 삼을 수 있어. 여러 글자 표식은 문자 클래스 하나와 같지 않으므로 별도 구조가 필요해.

Code

소유적 등가·python
import sys
import re

if sys.version_info >= (3, 11):
    # Possessive
    re.search(r'\d++X', 'aaa')   # 빠르게 실패 — 숫자부터 매칭되지 않아

    # Atomic 등가
    re.search(r'(?>\d+)X', 'aaa')

    # 둘 다 backtracking 폭발 보호
    # re.search(r'\d+X', '9'*30 + 'Y')  # backtracking 으로 더 느림
    # re.search(r'\d++X', '9'*30 + 'Y')  # 즉시 실패

# Portable workaround: .+? 대신 negated character class
# 나쁨 (greedy + backtrack)
re.search(r'".*?"', '"hello" world')

# 더 좋음 (backtrack 불가)
re.search(r'"[^"]*"', '"hello" world')

# 이게 모든 엔진 (JavaScript 와 RE2 포함) 에서 동작

External links

Exercise

.+?를 사용하는 패턴 하나를 골라 종료 문자가 분명하다면 [^X]* 형태로 다시 작성해. 두 패턴의 결과가 같은지 먼저 확인하고 긴 문자열에서 시간을 측정한 뒤, 속도와 엔진 호환성 차이를 기록해.

Progress

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

댓글 0

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

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