대안(alternation)과 그 활용
실제 애플리케이션을 개발하다 보면 두 개 이상의 후보 중 하나와 일치하는 정규 표현식을 자주 사용하게 됩니다. 또한 여러 표현식에 한꺼번에 수량자(quantifier)를 적용해야 하는 경우도 있습니다. 이러한 목표는 모두 괄호를 이용한 그룹화(grouping)로 달성할 수 있으며, 대안을 표현할 때는 세로 막대(vertical bar, |)를 사용합니다.
세로 막대(|) 사용하기
대안(alternation)은 여러 가지 서로 다른 패턴 중 하나라도 일치하면 되는 상황에서 유용합니다. 예를 들어 정규 표현식 airways|airplane|bomber는 airways, airplane, bomber 중 어느 하나라도 포함하는 텍스트와 일치합니다. 같은 결과는 air(ways|plane)|bomber로도 얻을 수 있습니다.
만약 (airways|airplane|bomber)라는 정규 표현식을 사용하면 세 표현식 중 하나와 일치하게 됩니다. 이번에는 (air(ways|plane)|bomber)를 살펴보겠습니다. 첫 번째 표현식이 일치하면 캡처가 두 개 생성되고(첫 번째 캡처는 airways 또는 airplane, 두 번째 캡처는 ways 또는 plane), 두 번째 표현식이 일치하면 캡처가 하나만 생성됩니다(bomber). 여는 괄호 바로 뒤에 ?:를 붙이면 다음과 같이 캡처 기능을 비활성화할 수 있습니다.
(air(?:ways|plane)|bomber)
이렇게 작성하면 일치했을 때 캡처가 하나만 생성됩니다(airways 또는 airplane 또는 bomber).
예제
다음 코드는 위에서 설명한 내용을 실제로 보여줍니다.
import re
s = 'airways aircraft airplane bomber'
result = re.findall(r'(airways|airplane|bomber)', s)
print(result)
result2 = re.findall(r'(air(ways|plane)|bomber)', s)
print(result2)
result3 = re.findall(r'(air(?:ways|plane)|bomber)', s)
print(result3)출력 결과
위 코드를 실행하면 다음과 같은 결과가 출력됩니다.
['airways', 'airplane', 'bomber']
[('airways', 'ways'), ('airplane', 'plane'), ('bomber', '')]
['airways', 'airplane', 'bomber']두 번째 출력에서 볼 수 있듯이 중첩된 그룹이 있으면 각 그룹별로 캡처가 반환되지만, ?:를 사용해 비캡처 그룹으로 만들면 전체 일치 결과만 깔끔하게 얻을 수 있습니다.