본문 바로가기
프로그래밍/정규표현식

[정규 표현식] 역 참조(Back reference) 알아보기

by 부자 꽁냥이 2022. 10. 1.

정규 표현식에는 검사 결과를 재활용할 수 있는 역 참조(Back Reference)라는 것이 있다. 검사 패턴으로 매칭된 결과를 다시 참조한다고 해서 역 참조라고 하는 것 같다. 이번 포스팅에서는 역참조에 대해서 알아보려고 한다.

 

이번 포스팅에서는 re.sub를 주로 사용하므로 사용법을 모르는 분들은 아래 포스팅을 미리 보고 오면 도움이 된다.

[정규 표현식] re 모듈 알아보기 (2) 대체하기 (feat. re.sub)

 

[정규 표현식] re 모듈 알아보기 (2) 대체하기 (feat. re.sub)

re 모듈에서 sub 함수는 특정 패턴이 일치하는 부분을 원하는 텍스트로 바꿔주는 기능을 한다. 오늘은 re.sub 함수 사용법을 알아보자.   re.sub 사용법 re 모듈에서 sub 함수는 특정 패턴이 일치하는

zephyrus1111.tistory.com


   역 참조(Back reference)에 대해서 알아보자.

1) 역 참조란?

역 참조는 특정 패턴 그룹이 매칭된 경우 매칭 결과를 참조하는 것을 의미한다. 역 참조는 패턴 그룹 즉, 괄호 '( )'으로 묶인 패턴을 매칭하는 경우 백 슬래시와 숫자 '\숫자' 형식으로 표현한다. 아래 그림은 문자열 1234hgi에 대하여 패턴 (\d+)\1을 검사하고 매칭 결과를 역 참조하는 과정을 나타낸 것이다. 

 

패턴 (\d+)은 문자열 1234를 매칭하고 \1로 표시된 곳에서 역 참조를 통하여 매칭 결과 1234를 저장하게 된다.

 

back reference 역 참조

 

그러나...

역 참조는 정말 좋은 기능이지만 패턴 매칭 작업에 역 참조라는 작업이 추가됨에따라 계산량이 많아질 수 있다. 따라서 용량이 큰 텍스트 파일에는 역 참조가 실행을 더 느리게 만들 수 있다.


2) 활용

이제 원리를 알았으니 코드를 통해서 테스트 해보자. 역 참조는 특정 패턴을 역 참조로 저장된 것으로 대체하거나 패턴으로 재활용할 수 있다.

a. 대체하기

아래 코드는 패턴 그룹 2개를 각각 역 참조 하여 문자열을 바꾸는 것이다.

 

import re

string = '010-1111'
re.sub(r'(\d+)-(\d+)', r'\2__\1', string) ## 역 참조 두 두번 일어난다.

 

위 코드의 동작 원리는 다음과 같다. 먼저 패턴 '(\d+)-(\d+)'이 010-1111을 매칭한다. 다음으로  첫 번째 패턴 그룹 '(\d+)'(파란 박스)이 010을 매칭하고 역 참조를 통해 \1에 저장된다. 두 번째 패턴 그룹 '(\d+)'(초록 박스)이 1111을 매칭하고 역 참조를 통해 \2에 저장된다. 마지막으로 매칭된 010-1111은 \2__\1에 의하여 1111__010으로 바뀌게 된다.

 

 

위 코드를 실행시키면 예상대로 문자열이 바뀌는 것을 알 수 있다.

b. 패턴으로 재활용

역 참조는 패턴으로 재활용할 때 사용될 수 있다. 특히 특정 패턴을 중심으로 좌우에 같은 문자가 있는 패턴을 추출할 때 많이 사용된다. 아래 코드는 알파벳과 공백으로 이루어진 문자열을 중심으로 좌우에 각 괄호 내부의 h와 숫자 조합을 갖는 패턴을 찾되 좌우가 똑같은 것을 매칭한 것이다. 좌우가 다른 <h3>My Blog<h5>은 매칭되지 않는다.

 

string = '<h1>Hello<h1>, <h2>World<h2>, <h3>My Blog<h5>'
pattern = re.compile(r'<(h[0-9])>[a-zA-Z\s]*<\1>')

print([x.group() for x in list(re.finditer(pattern, string))])

 

위 코드의 동작 원리는 다음과 같다. 다른 부분은 비슷하므로 여기서는 <h1>Hello<h1>를 매칭하는 과정을 보자. 먼저 패턴 <(h[0-9])>에 대하여 <h1>이 매칭된다 하지만 패턴 그룹 매칭 (h[0-9])에 의하여 h1이 저장되어 있다. 다음으로 뒤에 <\1>에 의하여 저장되어 있던 h1을 각 괄호 안으로 갖고 오게 된다. 이에 따라 명목 (코드 상) 패턴은 <(h[0-9])>[a-zA-Z\s]*<\1>이지만 실질 패턴은 <h1>a-zA-Z\s]*<h1>이 된다. 첫 번째 h1은 패턴 그룹 매칭에 의한 것이고 끝 부분 h1은 역 참조에 의한 것임을 잊지 말자.

 

따라서 최종적으로 <h1>Hello<h1>이 매칭된다. 물론 <h2>World<h2>가 매칭되는 것이다.

 

역 참조 원리

코드를 실행하면 예상했던 대로 매칭이 된 것을 알 수 있다.


댓글


맨 위로