지금까지 정규 표현식을 오해하고 있었던 이야기
TL;DR: /{\S*}/
-> {word}}
의 결과를 아시는 분은 재끼셔도 좋습니다.
우선 답부터
답부터 이야기하자면 {word}}
를 매칭합니다. 정규식을 배울 때 가장 처음에 배우는
내용(이라고 생각합니다) 중에 하나죠.
탐욕적인(Greedy) 패턴 매칭
한 문자, 또는 주어진 갯수만큼의 문자를 소비하면 되는 다른 정규식과는 달리,
조건에 맞는 문자를 한 개 이상(+
) 또는 0개 이상(*
)인 경우를 처리하는 경우에는
한가지 결정해야 할 부분이 있습니다. 그건 바로 조건에 맞는 경우가 한가지 이상일 때
이를 어떻게 다룰 것인가, 라는 부분인데요. 위에서 보였던 문제가 이에 해당합니다.
우선, {word}
는 주어진 정규 표현식을 만족시킬 수 있습니다. 물론 첫 번째 }
를
\S
로 매칭한 뒤 두번째 }
를 사용하여 {word}}
를 매칭할 수도 있죠.
정규표현식에서는 이 두 가지 중에서 후자를 사용하며, 이를 탐욕적이라고 표현합니다.
좀 더 일반적인 설명을 해볼까요. 탐욕적이라는 것은 현재 선택 가능한 매칭
후보군에서 가장 큰 덩어리를 취한다는 의미입니다. 예제를 더 봐보죠.
사용한 정규표현식: /{\S*}/
"{word}}"
#=> 후보군: "{word}" or "{word}}"
#=> 결과: "{word}}"
"{word1}-{word2}"
#=> 후보군: "{word1}" or "{word1}-{word2}"
#=> 결과: "{word1}-{word2}"
"{word1{word2}}"
#=> 후보군: "{word1{word2}" or "{word1{word2}}"
#=> 결과: "{word1{word2}}"
각각 취할 수 있는 가장 큰 덩어리를 매칭하는 것을 확인할 수 있습니다.
당신 나태(Lazy)하시군요?
물론 문자열 하나에서 다중 치환을 해야하는 경우에는 여러가지 의미로 귀찮아지기
때문에, 정규표현식에서는 탐욕적이지 않은 방식도 제공하고 있습니다.
각각의 수량자 뒤에 ?
를 사용하면, 현재 선택 가능한 매칭 후보군에서 가장 작은
덩어리를 취하게 됩니다. 탐욕적인 매칭과는 정반대로 동작하며 이를 나태(Lazy)한
방식이라고 표현합니다. 같은 예제를 사용하는 경우의 결과를 살펴보죠.
사용한 정규표현식: /{\S*?}/
"{word}}"
#=> 결과: "{word}"
"{word1}-{word2}"
#=> 결과: "{word1}"
"{word1{word2}}"
#=> 결과: "{word1{word1}"
간단하죠?
근데 이걸 몰랐어요?
네. 평범하게 앞에서부터 하나씩 문자를 소비해나가는 유한 오토마타라고 기억하고
있었기 때문입니다. 그래서 기본 소비가 나태하고, 옵션을 통해 탐욕적으로 소비하는
줄 알고 있었습니다…
결론
기초적인 사양도 가급적 꼼꼼히 읽읍시다.