탐욕적 수량자(Greedy Quantifier) & 게으른 수량자(Lazy Quantifier)


과하게 일치하는 상황 방지하기

RegEx: /<[Bb]>.*<\/[Bb]>

원하는 텍스트를 포함하긴 하지만, 찾으려 하지 않은 텍스트도 포함됐다. 그 이유는, 바로 별표(*)와 더하기(+) 같은 메타 문자가 탐욕적(greedy)이기 때문이다.

이는 가능한 한 가장 큰 덩어리를 찾으려 한다는 뜻이다. 이런 메타 문자는 찾으려는 텍스트를 앞에서부터 찾는 게 아니라, 텍스트 마지막에서 시작해서 거꾸로 찾는다. 의도적으로 수량자(quantifier)를 탐욕적으로 설계했기 때문이다.


하지만 만약 탐욕적 일치를 원하지 않는다면 어떻게 해야 할까? 

탐욕적 수량자를 게으른(lazy) 수량자로 바꾸면 된다. '게으른' 이라고 부르는 이유는 문자가 최소로 일치하기 때문이다. 게으른 수량자는 가존 수량자 뒤에 물음표(?) 를 붙여서 표현한다.

탐욕적 수량자에는 모두 각각 대응되는 게으른 수량자가 있다.


탐욕적 수량자와 게으른 수량자

 탐욕적 수량자

게으른 수량자 

 * 

 *? 

 + 

 +? 

 {n,} 

 {n,}? 



게으른 수량자를 이용

RegEx: /<[Bb]>.*?<\/[Bb]>

게으른 수량자인 *? 를 사용해 먼저 AK만 일치시켰고, 뒤이어 나머지도 찾아 두 부분을 따로 일치시켰다.



'Programming > RegEx' 카테고리의 다른 글

구간 지정  (0) 2013.05.12
반복 찾기(+, *) 와 '?' 메타 문자  (0) 2013.05.12
포직스(POSIX) 문자 클래스  (0) 2013.05.12
메타 문자 사용  (0) 2013.05.06
문자 집합으로 찾기  (0) 2013.05.06
Posted by scii
:

구간 지정

Programming/RegEx 2013. 5. 12. 21:46 |


구간 지정하기

더하기, 별표, 물음표는 정규 표현식을 쓰면서 발생하는 많은 문제를 해결해 주지만, 충분하지 않을 때도 있다. 다음과 같은 상황을 생각해 보자.

# 더하기와 별표는 일치하는 문자 수에 제한이 없다. 문자가 최대 몇 개까지 일치하는지 정할 수 없다.

# 더하기, 별표, 물음표가 일치하는 문자 수의 최솟값을 0이나 1이다. 일치하는 문자 수의 최솟값을 명시적으로 정의할 수 없다.

# 정확히 원하는 만큼만 일치하도록 문자 수를 정의할 수 없다.


이런 문제들을 해결하고, 연속하는 문자를 찾을 때 검색 조건을 더 구체적으로 지정하고자 정규 표현식에서는 구간을 사용한다.

구간은 중괄호([]) 안에 표시한다.



정확한 구간 찾기

문자가 일치하는 수를 정확히 정하려면 여는 중괄호와 닫는 중괄호 사이에 숫자를 넣는다. 즉 {3} 은 바로 앞에 있는 문자나 문자 집합이 세 번 연속해서 일치하는지 확인한다. 만약 요소가 두 개만 있다면, 패턴이 일치하지 않는다.

RegEx: 

16진수 여섯개가 일치하는 것을 검색



범위 구간 찾기

일치시키려는 요소 수의 최솟값과 최댓값을 나타낼 때도 구간을 사용한다. 범위는  {2,4} 처럼 표현한다. 최소 두 번에서 초대 네 번까지 일치시킨다는 의미이다.

RegEx: 

이 예제에서 쓴 정규식은 슬래시(/) 문자를 \/ 로 이스케이프 하였다. 많은 정규식 구현에서는 이 작업이 필요 없지만, 어떤 정규 표현식 해석기에는 필요하다. 

따라서 상 슬래시(/) 를 이스케이프 하는 편이 좋다.


※ 구간은 0부터 시작하기도 한다. {0,3} 은 요소가 없는 경우나 요소가 한 번 또는 두 번이나 세 번 일치함을 의미한다.

물음표(?)는 물음표 앞에 주어진 요소가 없는 경우나 요소 한개와 일치한다. 즉, 물음표(?) 는 {0,1} 과 같은 기능을 한다.



최소 구간 찾기

예를 들어 {3,} 은 최소한 요소가 세 번 일치함을 의미한다. 

RegEx: 


※ 더하기(+) 는 {1,} 과 기능이 같다.


'Programming > RegEx' 카테고리의 다른 글

Greedy Quantifier & Lazy Quantifier  (0) 2013.05.12
반복 찾기(+, *) 와 '?' 메타 문자  (0) 2013.05.12
포직스(POSIX) 문자 클래스  (0) 2013.05.12
메타 문자 사용  (0) 2013.05.06
문자 집합으로 찾기  (0) 2013.05.06
Posted by scii
:


문자 하나 이상 찾기

문자나 집합에 속한 요소를 하나 이상 찾으려면 간단히 문자 뒤에 더하기(+) 문자를 붙이면 된다. 더하기(+)는 문자가 하나 이상일 때 일치한다. (최소한 하나와 알치하고, 없을 때는 일치하지 않는다)

a가 a를 찾는 데 반해, a+는 하나 이상 연속된 a를 찾는다. 비슷하게 [0-9] 는 자릿수가 하나인 숫자를 찾는 데 반해, [0-9]+ 는 한 자리 이상 연속된 숫자를 찾는다.


TIP

문자 집합에 더하기(+)를 사용할 때는, 더하기(+)를 집합 바깥에 두어야 한다. 즉 [0-9+] 가 아니라 [0-9]+ 가 맞는 표현이다.

[0-9+] 가 틀린 정규 표현식은 아니지만, 하나 이상의 숫자와 일치하지는 않는다. 더 정학히 말하면 숫자 0부터 9와 더하기(+)로 집합을 정의한 것이고, 따라서 아무 한 자리 숫자나 더하기 기호와 일치하게 된다. 

문법에는 맞지만, 원하는 결과는 아닐 것이다.



현재 블로그에 올리는 예제들은 vim에서 하고 있다. 그래서 본래의 정규식과 이스케이프되야하는 상황이 살짝 다르다. 

이를 테면, 정규식에서는 그냥 + 만 쓰지만, vim에서는 \+ 써야 한다.



이메일 주소를 검색하는 예제

RegEx: 


위의 예제에서 마지막에 \.\w\+ 이 부분을 주의해야 한다. 

이것은, 검색하는 문자열이 맨 마지막에 무조건 .(dot) 다음에 문자가 와야 한다는 것을 명시한 것이다. 저것을 빼면 이메일 주소 마지막에 .(dot) 까지 검색이 된다. 

하지만, 맨 마지막에 위와 같이 명시를 하면 정확히 이메일 주소만 검색을 할 수 있다. 


※ 이 패턴을 보고 집합 안에서는 마침표(.) 를 이스케이프 하지 않아도 마침표와 일치한다는 사실을 알 수 있다. 일반적으로 마침표나 더하기 같은 메타 문자들이 집합의 구성원일 때는 문자 그대로 취급하기 때문에, 굳이 이스케이프 할 필요가 없다. 

그러나 이스케이프 한다고 문제가 생기지는 않는다. [\w.] 는 [\w\.] 와 기능이 같다.




자가 없는 경우나 하나 이상 연속하는 문자 찾기

더하기는 하나 이상 연속된 문자를 찾는다. 문자가 없는 경우는 아예 찾지 못하고, 최소한 하나는 일치해야 한다. 

그래서 있을 수도 있고 없을 수도 있는 문자와 일치시키려면 메타 문자인 별표(*) 를 사용해야 한다.

따라서 B.* Forta 패턴은 B Forta, B. Forta, Ben Forta 같은 조합과 일치한다.


RegEx: 

위와 같은 이메일 주소는 없지만, 가상으로 만들어서 검색을 한 것이다.

맨 처음 \w\+는 처음에 오는 이메일 주소가 유효하고 그다음 . 이 있을 수도 없을 수도 있다는 것이다.




문자가 없거나 하나인 문자 찾기

별표(*) 처럼 물음표(?) 는 문자가 있는 경우 일치하고 문자가 없어도 일치하지만, 별표(*) 와 달리 문자나 집합이 없거나 하나만 있는 경우만 일치하며, 하나 이상은 일치하지 않는다.

즉, 물음표(?) 는 문자 묶음 안에서 있는지 없는지 확실하지 않은 특정한 문자를 하나만 찾을 때 매우 유용하다.


RegEx: 


이 패턴은 https?:// 로 시작한다. 물음표(?)는 자기 앞에 있는 문자가 없거나 그 문자가 하나만 있는 경우 일치한다. 여기서는 s인데, https?:// 는 http:// 나 https:// 와 일치하지만, 그 외에는 일치하지 않는다.


TIP:

집합([]) 은 일반적으로 문자 집합을 정의하는 데 쓰지만, 일부 개발자들은 혼란을 방지하고자 문자가 하나일 때도 집합을 사용한다. 바로 뒤에 나오는 메타 문자가 정확하게 어디에 적용되는지 확실하게 하려는 것이다.

즉, 위의 예제는 아래와 같이 확실하게 명시적으로 쓸 수 있다.

http[s]?://


'Programming > RegEx' 카테고리의 다른 글

Greedy Quantifier & Lazy Quantifier  (0) 2013.05.12
구간 지정  (0) 2013.05.12
포직스(POSIX) 문자 클래스  (0) 2013.05.12
메타 문자 사용  (0) 2013.05.06
문자 집합으로 찾기  (0) 2013.05.06
Posted by scii
:


포직스는 줄여 쓰기를 나타내는 또 다른 형태인데, 전부는 아니지만 많은 정규 표현식 구현에서 지원한다.


POSIX 문자 클래스

POSIX 문자

 [:alnum:]

 [A-Za-z0-9] 알파벳 문자와 숫자로 이루어진 문자열

 [:alpha:]

[A-Za-z] 알파벳 문자 

 [:blank:]

[ /x09] 스페이스와 탭(\t ]와 같다)

 [:digit:]

[0-9] 숫자 

 [:graph:]

[!-~] 공백이 아닌 문자 (스페이스, 제어 문자들을 제외한 문자) 

 [:lower:]

[a-z] 소문자 

 [:print:]

[-~] [:graph:] 와 유사하지만 스페이스 문자를 포함 

 [:punct:]

[!-/:-@[-{-~] 문장 부호 문자([:alnum:]이나 [:cntrl:]가 포함되지 않은 모든 문자

 [:space:]

[ \t\v\f] 모든 공백 문자(newline 줄바꿈, 스페이스, 탭) 

 [:cntrl:]

컨트롤 제어 문자 (아스키 0번부터 31, 127번)

 [:upper:]

[A-Z] 대문자 

 [:xdigit:]

[0-9a-fA-F] 16진수에서 사용할 수 있는 숫자 


※ POSIX

이식 가능 운영체제 인터페이스(portable operating system interface), 또는 포직스는 서로 다른 유닉스 os의 공통 api 를 정리하여, 이식성이 높은 유닉스 응용 프로그램을 개발하려는 목적으로 IEEE가 책정한 애플리케이션 인터페이스 규격이다. 



RegEx: [[:xdigit:]]\+


여기서 사용한 정규 표현식이 [[로 시작해서 ]] 로 끝남을 유의하자. 이는 포직스 클래스를 사용할 때 매우 중요하고 필수적이다. 포직스 클래스는 [:로 시작해 :] 로 끝나기 때문에 우리가 사용하는 포직스 문법은 :xdigit: 가 아니라 [:xdigit:] 이다. 

따라서 바깥에 있는 대괄호는 집합을 정의하고, 안에 있는 대괄호는 포직스 클래스 자체를 나타내는 부분이다.



'Programming > RegEx' 카테고리의 다른 글

구간 지정  (0) 2013.05.12
반복 찾기(+, *) 와 '?' 메타 문자  (0) 2013.05.12
메타 문자 사용  (0) 2013.05.06
문자 집합으로 찾기  (0) 2013.05.06
정규 표현식(Regualr Expression)  (0) 2013.05.05
Posted by scii
:


공백 문자 찾기

정규 표현식 검색을 수행할 때, 눈에 보이지 않지만 텍스트에 포함되는 공백 문자들도 찾아야 할 때가 있다.

예를 들어, 탭 문자를 모두 찾거나 줄바꿈 문자를 찾고 싶을 수도 있다. 꼼수를 이용하지 않고 이런 문자를 정규 표현식에 직접 써넣기가 어렵기 때문에, 아래와 같은 특수한 메타 문자들을 사용할 수 있다.


공백 메타 문자

 메타 문자

설 명 

 [\b]

 백스페이스 

 \f  

 페이지 넘김(form feed) 

 \n 

 줄 바꿈 

 \r 

 캐리지 리턴 

 \t 

 탭 

 \v 

 수직 탭


ex) \r\n\r\n

\r\n은 줄 바꿈과 캐리지 리턴의 조합과 일치한다. 위도우에서 이 조합은 줄의 끝을 나타내는 데 사용한다.

따라서 \r\n\r\n 을 검색하면, 줄 끝이 연속해서 두 번 나오는 부분과 일치하는데, 이때 줄의 끝이 두 번 나온다는 것은 바로 두 레코드 사이에 빈 줄이 있음을 의미한다.



특정한 문자 형태와 일치시키기

문자 집합은 검색에서 쓰는 가장 흔한 형태이기에, 자주 쓰는 문자 집합들은 특수한 메타 문자로 대신하기도 한다. 

이러 테마 문자들을 문자 클래스(classes of characters)라고 부른다. 직접 찾고 싶은 문자들을 열거하거나 범위를 사용하면 되기 때문에, 실제로 클래스 메타 문자를 써야만 하는 경우는 결코 없지만, 사용해 보면 너무나도 유용함을 알게 될 것이다.


다음은 거의 모든 정규 표현식 구현에서 기본으로 지원하는 클래스들이다.


숫자 메타 문자

메타 문자 

설 명 

 \d 

 숫자 하나([0-9])와 같다. 

 \D 

 숫자를 제외한 문자 하나([^0-9]와 같다) 


regex: myArray\[\d\+\]


※ 정규 표현 문법은 대소문자를 구별한다. \d는 숫자 하나와 일치하고, \D는\d와 뜻이 정반대다. 

클래스 메타 문자에서도 소문자와 대문자는 서로 반대임을 뜻한다.



영숫자 문자와 영숫자가 아닌 문자 찾기

자주 사용하는 문자 집합이 또 있다. 영숫자(alphanumeric) 문자로, 대문자와 소문자를 포함한 알파벳 A부터 Z, 숫자, 밑줄을 포함한다.

대개 파일이나 디렉토리 이름, 애플리케이션 변수명, 데이터베이스 객체 이름 등에 사용한다.


영숫자 메타 문자

 메타 문자 

설 명 

 \w 

 대소문자와 밑줄을 포함하는 모든 영숫자([a-zA-Z0-9_]와 같다) 

 \W 

 영수자나, 밑줄이 아닌 모든 문자(^a-zA-Z0-9_]와 같다) 



regex: 


'Programming > RegEx' 카테고리의 다른 글

반복 찾기(+, *) 와 '?' 메타 문자  (0) 2013.05.12
포직스(POSIX) 문자 클래스  (0) 2013.05.12
문자 집합으로 찾기  (0) 2013.05.06
정규 표현식(Regualr Expression)  (0) 2013.05.05
태그 찾기  (0) 2013.02.12
Posted by scii
:


여러 문자 중 하나와 일치시키기
모든 문자가 아니라 다만 n이나 s와 일치하는 파일명만 찾고 싶을 때 정규 표현식에서는 메타 문자인 대괄호([ ])를 사용해 문자 집합을 표현한다.
대괄호([ ])안에 있는 문자는 모두 집합의 구성원이 되며, 집합에 속한 문자 가운데 하나가 일치한다. 집합에 속한 문자가 모두 일치할 필요는 없다.


정규 표현식: [ns]a.\.

분석: 이 패턴은 n이나 s중 한 문자와 일치하며, c나 다른 문자와는 일치하지 않는다. 대괄호([ ])는 집합을 의미하기 때문에 대괄호 자체는 어떤 문자와도 일치하지 않는다. 대괄호([ ])는 집합을 의미하기 때문에 대괄호 자체는 어떤 문자와도 일치하지 않는다. 문자 a는 a와 일치하고 마침표(.)는 모든 문자와 일치한다.


※ 실제로 이런 상황에서 [ns]a.\. 는 정답이 아니다. 만약 파일명 가운데 usa1.xls가 있다면, 해당 파일명 역시 정규 표현식과 일치하기 때문이다. 

이 문제를 해결하려면 위치도 지정해서 찾아야 한다.


위의 상황은 이것으로도 할 수 있다.

[ns]a[0-9]\.


※ 하이픈(-)은 대괄호([ ]) 안에서만 메타 문자인 특수한 메타 문자다. 

집합 밖에서 하이픈(-)은 단순히 문자 그대로 하이픈(-)과 일치한다. 그래서 집합 밖에서는 하이픈(-) 문자에 굳이 역슬래시(\)를 붙일 필요가 없다.



제외하고 찾기

문자 집합은 일반적으로 찾고 싶은 문자의 목록을 정하는 데 쓰지만, 반대로 찾을 때 제외하고 싶은 문자 목록을 정할 때도 쓸 수 있다. 

다른 말로, '여기서 지정한 목록을 제외하기' 라고 할 수 있다.


캐럿(^) 문자를 써 제외할 문자 집합을 지정한다.

캐럿(^)문자는 이 문자 바로 뒤에 있는 문자나 범위뿐만 아니라 집합 안에 있는 문자나 범위를 모두 제외한다.


regex: [ns]a[^0-9]\.


정리:

메타 문자인 대괄호([ ])는 문자 집합을 정의하는데, 그 집합 구성원 중에 한 문자라도 일치해야 한다.(and 가 아닌 or이다). 문자 집합은 문자를 일일이 열거하거나 하이픈(-)문자를 사용해 범위를 설정할 수 있다. 

또 캐럿(^)문자는 지정한 문자들을 제외한 어떤 것들과 일치시킨다.


'Programming > RegEx' 카테고리의 다른 글

포직스(POSIX) 문자 클래스  (0) 2013.05.12
메타 문자 사용  (0) 2013.05.06
정규 표현식(Regualr Expression)  (0) 2013.05.05
태그 찾기  (0) 2013.02.12
[Python] Regular Expression  (0) 2013.02.07
Posted by scii
:


정규 표현식(Regular Expression, 줄여서 레젝스(regex)라고도 한다)은 도구다.

그리고 다른 도구들과 마찬가지로 특정한 문제를 해결할 목적으로 만들어졌다 .


정규 표현식을 사용하는 이유는, 검색과 치환이 전부이다. 

모든 정규 표현식은 일치하는 텍스트를 찾거나(검색) 텍스트를 찾은 뒤에 그것을 원하는 텍스트로 치환한다.(치환)


정규 표현식의 예)

정규 표현식 명령: .a.\.

마침표(.)는 한 문자와 일치한다.

역슬레시(\) 문자들이 문자 그대로 해석되게 한다(이스케이프). 특수한 문자 시퀀스를 시작하는 데 사용된다.


※ 마침표(.)는 모든 문자와 알치하지 않을 수 도있다. 하지만 대다수 정규 표현식 구현에서 마침표(.)는 줄바꿈(newline) 문자를 제외한 모든 문자와 일치한다.


'Programming > RegEx' 카테고리의 다른 글

메타 문자 사용  (0) 2013.05.06
문자 집합으로 찾기  (0) 2013.05.06
태그 찾기  (0) 2013.02.12
[Python] Regular Expression  (0) 2013.02.07
URL 교체하기  (0) 2013.02.03
Posted by scii
:

태그 찾기

Programming/RegEx 2013. 2. 12. 19:45 |



'Programming > RegEx' 카테고리의 다른 글

문자 집합으로 찾기  (0) 2013.05.06
정규 표현식(Regualr Expression)  (0) 2013.05.05
[Python] Regular Expression  (0) 2013.02.07
URL 교체하기  (0) 2013.02.03
정규 표현식의 활용(이메일 주소 변경)  (0) 2013.02.03
Posted by scii
: