본문 바로가기
프로그래밍 놀이터/Tips

[도서 정리] 9. 전방탐색과 후방탐색 - 손에 잡히는 10분 정규 표현식

by 돼지왕 왕돼지 2019. 12. 31.
반응형

9. 전방탐색과 후방탐색 - 손에 잡히는 10분 정규 표현식



-

지금까지 사용한 표현식들은 모두 일치하는 텍스트를 가지고 있었지만, 가끔은 텍스트 자체를 찾기보다는 어디서 텍스트를 찾을지를 표시하는데 표현식을 쓰고 싶을 때도 있다.

그러려면 전후방탐색(lookaround)을 써야 한다.





* 전후방탐색 살펴보기


-

전방탐색은 모든 주요 정규식 구현에서 지원하지만, 후방탐색은 광범위하게 지원하지 않는다.

자바, 닷넷, PHP, 파이썬, 펄에서는 몇 가지 제약이 있지만 후방탐색을 지원한다.

자바스크립트에서는 지원하지 않는다.





* 전방탐색 - 앞으로 찾기


-

전방탐색(lookahead) 패턴은 일치 영역을 발견해도 그 값을 반환하지 않는 패턴을 말한다.

전방탐색은 실제로는 하위 표현식이며, 하위 표현식과 같은 형식으로 작성한다.

전방탐색 패턴의 구문은 ?=로 시작하고 등호(=) 다음에 일치한 텍스트가 오는 하위 표현식이다.



-

일부 정규식 문서에서는 일치하는 영역을 반환하는 동작을 표현할 때 '소비한다(consume)'는 용어를 쓴다.

이럴 경우 전방탐색은 ‘소비하지 않는다(not consumed)’고 말한다.



-

http://www.naver.com/

https://mail.naver.com/

ftp://ftp.naver.com/


.+(?=:)

위 정규식을 적용하면 프로토콜 영역만 추출해 올 수 있다. ( : 는 매칭은 하지만 찾은 범위로 표시되지 않는다. )



-

전방탐색(후방탐색) 일치는 실제로 결과를 반환하지만, 반환된 문자의 길이가 항상 0이다.

따라서 전방탐색을 흔히 ‘제로 폭(zero-width)’이라 부르기도 한다.



-

모든 하위 표현식 앞쪽에 단순히 ?=를 붙이기만 하면 전방탐색 표현으로 바꿀 수 있다.

하나의 검색 패턴 속에서 여러 개의 전방탐색 표현식을 사용할 수 있고, 또한 그 표현식은 패턴 안에서 어느 위치에서든 사용할 수 있다.

앞에서 본 예제처럼 하위 표현식의 제일 앞에 오지 않아도 된다.





* 후방탐색 - 뒤로 찾기


-

?= 는 앞으로 탐색한다.

일치하는 텍스트 다음에 무엇이 오는지 찾고, 발견한 텍스트 자체는 소비하지(consume) 않는다.

따라서 ?= 는 전방탐색 연산자라 부른다.

많은 정규식 구현에서 전방탐색과 더불어 후방탐색(lookbehind) 기능도 지원한다.

텍스트를 반환하기 전에 탐색하는 작업은 뒤쪽을 탐색하기도 포함한다.

후방탐색 연산자는 ?<= 이다.



-

?<= 는 ?= 와 사용 방법이 같다.

즉, 하위 표현식 안에서 사용하고, 일치할 텍스트 앞에 온다.



-

아래 예제에서 가격만 뽑고 싶다면


ABC01: $23.45

HGG42: $5.31

CFMX1: $899.00


\$[0-9.]+ 정규식을 대입할 수 있다.


그러나 숫자만 뽑고 싶다면..


(?<=\$)[0-9].+



-

전방탐색 패턴은 마침표(.)와 더하기(+)를 포함하여 텍스트의 길이를 다양하게 일치시킬 수 있으며, 매우 동적이다.

반대로 후방탐색 패턴은 보통 일치시킬 텍스트의 길이를 고정해야 한다.

거의 모든 정규식 구현에는 이런 제약이 있다.








* 전방탐색과 후방탐색 함께 사용하기


-

<head>

<title>Gamza homepage</title>

</head>


여기서 title 내용을 뽑고 싶다면...


(?<=<[Tt][Ii][Tt][Ll][Ee]>).*(?=<\/[Tt][Ii][Tt][Ll][Ee]>)





* 부정형 전후방탐색


-

후방탐색과 전방탐색은 반환할 텍스트의 위치, 즉 찾고자 하는 부분의 앞뒤를 특별히 지정하고 싶을 때 주로 사용했다.

이런 방법들을 긍정형 전방탐색과 긍정형 후방탐색이라고 한다.

긍정(positive)이라는 말을 쓰는 이유는 실제로 일치하는 텍스트를 찾기 때문이다.



-

전후방탐색 중에서 부정형(negative) 전후방탐색은 비교적 덜 쓰는 방법이다.

부정형 전방탐색은 앞쪽에서 지정한 패턴과 일치하지 않는 텍스트를 찾고, 부정형 후방탐색도 이와 비슷하게, 뒤쪽에서 지정한 패턴과 일치하지 않는 텍스트를 찾는다.



-

(?=) : 긍정형 전방 탐색

(?!) : 부정형 전방 탐색

(?<=) : 긍정형 후방탐색

(?<!) : 부정형 후방탐색



-

대개 전방탐색을 지원하는 정규식 구현은 긍정형과 부정형 전방탐색을 모두 지원한다.

마찬가지로 후방탐색을 지원하는 구현에서도 긍정형과 부정형 후방탐색 모두 지원한다.



-

I paid $30 for 100 apples.


여기서 $ 를 제외한 가격 숫자를 찾으려면...

(?=\$)\d+


갯수 숫자를 찾으려면....

\b(?!\$)\d+\b

여기서 \b 가 들어간 이유는… $30 의 0 이 찾아지기 때문이다.





* 요약


-

전방탐색과 후방탐색을 사용하면, 무엇을 반환할지 더 구체적으로 명시할 수 있다.

전후방탐색 명령어는 하위 표현식을 통해 텍스트의 위치를 지정하지만, 소비하지는 않는다.

일치하지만, 일치한 텍스트 자체에는 포함하지 않는다는 이야기다.

긍정형 전방탐색을 (?=)로 정의하고, 부정형 전방탐색은 (?!)로 정의한다.

몇몇 정규식 구현에서는 (?<=)로 긍정형 후방탐색을 지원하고, (?<!)로 부정형 후방탐색을 지원한다.





반응형

댓글