References
- Learning Regular Expressions
Contents
- 이스케이프 문자
- 공백 문자 찾기
- 특정한 문자 타입과 일치시키기 (숫자, 영숫자, 공백)
- POSIX 문자 클래스
이전 포스팅에서 간단한 메타 문자를 살펴봤습니다. 이번에는 특별한 문자나 문자 타입과 일치하는 메타 문자에 대해서 알아보도록 하겠습니다.
이스케이프 살펴보기
메타 문제에 대해 더 깊이 알아보기 전에 이스케이프(excape)에 대해 이해하는 시간을 먼저 가져보도록 하겠습니다.
메타 문자는 정규표현식 안에서 특별한 의미가 있습니다. 마침표(.)는 메타 문자로, 어떤 문자든 문자 하나와 일치합니다. 이와 유사하게, 여는 대괄호([)도 집합의 시작을 나타내는 메타문자입니다.
메타 문자들은 정규표현식에서 특별한 의미가 있으므로 자기 자신을 문자 그대로 표현할 수가 없습니다. 여는 대괄호가 '['와 일치하지 않고, 마침표가 '.'와 일치하지 않는다는 의미입니다.
다음 예제를 살펴보겠습니다. 주어진 예문에서 여는 대괄호([)와 닫는 대괄호(])를 포함하는 자바스크립트 배열을 찾으려고 하는 예제입니다. 여기서 사용한 정규표현식은 'myArray[0]' 입니다.
예제에서 사용한 예문은 자바스크립트 코드의 일부입니다. 정규표현식은 문서 에디터에서 사용할 법한 형태를 그대로 입력했습니다. myArray[0]과 일치하리라고 생각할 수 있지만, 실제로 일치하지 않습니다. 이는 대괄호([])는 정규표현식 안에서 집합을 정의하는 정규 표현 메타 문자로, 문제 그대로의 대괄호를 의미하지 않기 때문입니다. 따라서 'myArray[0] 패턴은 myArray 문자열과 일치하고 동시에 집합에 속한 구성원 중 한 문자와 일치합니다. 여기서는 0이 집합의 유일한 구성원이므로 이 정규표현식은 myArray0과 일치합니다.
이전 포스팅에서 언급했었는데, 메타 문자는 그 앞에 역슬래시(\)를 붙여 문자 그대로 해석되도록(이스케이프) 할 수 있습니다. 즉, '\.'는 '.'와 일치하고 '\['는 '['와 일치합니다. 메타 문자는 모두 이스케이프할 수 있는데, 그러면 메타 문자로서 지니는 특별한 의미 대신 문자 자체를 뜻하게 됩니다.
다음 예제에서는 메타 문자들을 이스케이프하여, 'myArray\[0\]' 패턴을 사용한 결과입니다.
이번에는 제대로 검색되었습니다. '\['는 '['와 일치하고, '\]'는 ']'와 일치합니다.
여기서 사용한 정규표현식은 다소 불필요해 보입니다. 단순한 텍스트 검색만으로도 충분히 만족스러운 결과를 더 쉽게 얻을 수 있습니다. 하지만 단순히 myArray[0]뿐만 아니라 myArray[1], myArray[2] 같은 배열도 찾으려면 어떻게 해야할 지 상상해 봅시다. 이런 경우에는 정규표현식을 사용하는 것이 더 유용합니다. 여는 대괄호와 닫는 대괄호는 이스케이프하고, 두 문자 사이에 원하는 문자들이 일치하도록 조건을 정하면 됩니다. 만약 배열 요소를 0부터 9까지 일치시키고 싶다면 다음과 같이 정규표현식을 작성할 수도 있습니다.
'myArray\[[0-9]\]'
역슬래시(\)는 메타 문자들을 이스케이프하는 데 사용됩니다. 이 말은 역슬래시도 메타 문자이며, 다른 메타 문자들을 이스케이프 하는 데 사용된다는 뜻입니다. 따라서 역슬래시 문자 자체를 나타내고 싶으면 '\\'로 이스케이프 해야 합니다.
다음의 간단한 예문을 살펴보겠습니다.
\home\jun\sales\
윈도우에서 볼 수 있는 역슬래시를 이용한 파일 경로인데, 이 경로를 리눅스에서 사용하다는 가정하에 모든 역슬래시를 찾아 슬래시로 변경해보도록 하겠습니다. 여기서 '\\' 패턴을 사용합니다.
'\\'는 역슬래시와 일치하며 4개가 일치했습니다. 정규표현식에서 역슬래시만을 사용했다면, 정규표현식 분석기가 정규표현식을 다 작성하지 않았다고 판단하여 아마 에러가 발생했을 것입니다. 따라서 정규표현식에서는 역슬래시 뒤에 반드시 다른 문자를 함께 써넣어야 합니다.
공백 문자 찾기
메타 문자는 일반적으로 2가지 카테고리로 나눌 수 있습니다. 마침표처럼 텍스트와 일치하는 문자와 여는 대괄호나 닫는 대괄호처럼 정규표현식의 문법의 일부로 쓰는 문자입니다.
이제 공백 문자를 살펴보면서 두 가지 유형의 메타 문자들을 더 많이 접할 것입니다. 우선 공백 메타 문자부터 시작해보도록 하겠습니다.
정규 표현식 검색을 수행할 때, 우리는 눈에 보이지 않지만 텍스트에 포함되는 공백 문자들을 찾아야 할 때가 있습니다. 예를 들어 탭 문자를 모두 찾거나 줄바꿈(line break) 문자를 찾고 싶을 수도 있습니다. 꼼수를 이용하지 않고 이런 문자를 정규표현식에 직접 써넣기는 어려우므로 아래의 표에 있는 특수한 메타 문자들을 사용할 수 있습니다.
다음 예문을 살펴보겠습니다. 이 예문에는 콤마로 구분된(일반적으로 CSV) 레코드가 담겨 있습니다.
"101","Ben","Forta"
"102","Jim","James"
"103","Roberta","Robertson"
"104","Bob","Bobson"
그리고 이 데이터에 있는 빈 줄을 모두 제거한 다음, 이 레코드를 처리해야 한다고 가정해봅시다.
이 작업을 위해서는 '\r\n\r\n' 패턴을 사용해야 합니다.
제가 테스트하는 사이트에서는 '\r\n\r\n'이 아닌 '\n\n'을 사용해야 위와 같이 검색이 되었습니다.
윈도우에서 노트패드를 사용하여 정규표현식으로 '\r\n\r\n'을 검색하면 다음의 결과를 얻을 수 있습니다.
여기서 '\r\n'은 줄바꿈과 캐리지 리턴의 조합과 일치합니다. 윈도우에서 이 조합은 줄의 끝을 나타내는 데 사용됩니다. 따라서 노트패드에서 이 패턴으로 검색하면, 줄 끝이 연속으로 두 번 나오는 부분과 일치하는데, 이때 줄의 끝이 두 번 나온다는 것은 바로 두 레코드 사이에 빈 줄이 있다는 것을 의미합니다.
(유닉스와 리눅스, Mac OS X 시스템에서는 단순히 줄바꿈 문자만 사용합니다. 따라서 이러한 시스템에서는 \r은 제외하고 \n만 사용해야 합니다. 이상적인 정규표현식 패턴에서는 \n이 필수고, \r은 경우에 따라 처리할 수 있어야 하는데, 이에 대해서는 다음 포스팅에서 다루도록 하겠습니다.)
공백 문자 가운데서는 \r, \n, \t를 가장 많이 사용하고, 나머지 공백 문자들은 자주 사용되지는 않습니다.
특정한 문자 타입와 일치시키기
지난 포스팅들부터 지금까지 특정 문자, 모든 문자('.' 사용), 문자 집합 가운데 하나(대괄호 '[]' 사용)를 어떻게 찾는지 알아보고, 어떻게 문자를 제외하는지도('^' 사용) 알아봤습니다. 문자 집합은 검색에서 쓰는 가장 흔한 형태이기 때문에, 자주 쓰는 문자 집합들은 특수한 메타 문자로 대신하기도 합니다. 이런 메타 문자들을 문자 클래스(classes of characters)라고 부릅니다. 직접 찾고 싶은 문자들을 열거하거나 범위를 사용하면 되기 때문에, 실제로 클래스 메타 문자를 써야만 하는 경우는 거의 없지만, 일단 사용해보면 너무나 유용하다는 것을 알게 됩니다.
숫자와 숫자가 아닌 문자 찾기
'[0-9]' 패턴은 '[0123456789]'를 줄인 표현이고 어떤 숫자와도 일치합니다. 숫자를 제외한 문자를 찾으려면, '[^0-9]'처럼 제외하는 메타 문자를 사용합니다. 다음의 표는 숫자와 숫자가 아닌 문자를 더 간단하게 표현하는 클래스를 보여줍니다.
앞에서 봤던 자바스크립트 예문을 가지고, 이 메타 문자를 어떻게 쓰는지 살펴보겠습니다.
아래 결과는 'myArray\[\d\]' 패턴으로 검색한 결과입니다.
'\['는 여는 대괄호([)와 일치하고, '\d'는 숫자 하나와 일치하고, '\]'는 닫는 대괄호(])와 일치하므로, 이 패턴은 myArray[0]과 일치합니다. 즉, 'myArray\[[0123456789]\]'는 'myArray\[[0-9]\]'로, 'myArray\[[0-9]\]'는 다시 'myArray\[\d\]'로 줄여서 표현한 것입니다. 이 정규표현식은 myArray[1], myArray[2]와 같은 표현도 일치하지만, myArray[10]과는 일치하지 않습니다.
정규표현 문법은 대소문자를 구분합니다. '\d'는 숫자 하나와 일치하고, '\D'는 '\d'와 뜻이 정반대입니다. 앞으로 살펴 볼 클래스 메타 문자에서도 소문자와 대문자는 서로 반대임을 뜻합니다. 대소문자를 구분하지 않고 검색을 수행할 때도 정규표현식 문법은 대소문자를 구분합니다. 따라서, 찾으려는 텍스트는 대소문자를 구분하지 않더라도, '\d' 같은 특수한 문자는 대소문자를 구분합니다.
영숫자 문자와 영숫자가 아닌 문자 찾기
자주 사용하는 문자 집합이 또 있는데, 바로 영숫자(alphanumeric) 문자입니다. 이 문자 집합은 대문자와 소문자를 포함한 알파벳 A부터 Z, 숫자, 밑줄을 포함합니다. 아래의 표는 영숫자가 아닌 문자를 간단하게 표현한 클래스를 보여줍니다.
다음 예문을 통해 살펴보겠습니다. 이 예문은 미국과 캐나다의 우편번호 데이터베이스을 일부입니다.
11213
A1C2E3
48075
48237
M1B4F2
90046
H1H2H2
여기서 정규표현식 '\w\d\w\d\w\d' 패턴을 사용하면, 다음의 결과를 얻을 수 있습니다.
여기서는 메타 문자 '\w'와 '\d'를 조합한 패턴을 사용했는데, 캐나다 우편번호만을 찾아냅니다.
공백 문자와 공백이 아닌 문자 찾기
마지막으로 살펴 볼 내용은 공백 클래스입니다. 이번 포스팅 초반에 특정 공백 문자를 나타내는 메타 문자들에 대해 알아봤습니다. 다음의 표는 공백 문자를 모두 표현하는 클래스를 보여줍니다.
'\s'와 '\S'에는 백스페이스 메타 문자인 [\b]는 포함되지 않습니다.
16진수나 8진수 표현하기
16진수 값은 앞에 \x를 붙여 표시합니다. 즉, \x0A(아스키 문자 10)은 줄바꿈 문자가 되며 \n과 기능이 같습니다.
8진수 값은 두 자리나 세 자리 정수 앞에 \0을 붙여 표시합니다. 즉, \011(아스키 문자 9)는 탭 문자이며, \t와 기능이 같습니다.
많은 정규표현식 구현에서는 \c 문자를 이용해 컨트롤 문자를 표현합니다. 예를 들어, \cZ는 Ctrl-Z와 일치합니다. 실제로 거의 사용되지는 않는 문법입니다.
POSIX 문자 클래스
메타 문자와 여러 문자 집합을 줄여 쓰는 방법에 대한 설명에서 POSIX 문자 클래스가 빠질 수 없습니다. 이 문자 클래스는 줄여 쓰기를 나타내는 또 다른 형태인데, 전부는 아니지만 많은 정규표현식 구현에서 지원합니다.
자바스크립트는 정규표현식에서 POSIX 문자 클래스를 지원하지 않습니다.
아래의 표는 POSIX 문자 클래스들을 보여줍니다.
POSIX 문법은 지금까지 봐온 메타 문자와는 사뭇 다릅니다.
다음의 예제로 POSIX 클래스를 테스트해보도록 하겠습니다. 이 예문은 HTML 코드이며, 여기서 RGB값을 찾도록 하겠습니다. 이 예제는 [REGEX] 문자 집합으로 찾기 포스팅에서 살펴본 적이 있습니다.
body {
background-color: #fefbd8;
}
h1 {
background-color: #0000ff;
}
div {
background-color: #d0f4e6;
}
span {
background-color: #f08970;
}
다음의 정규표현식으로 RGB값을 찾을 수 있습니다.
'#[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]'
이 패턴을 사용한 결과는 다음과 같습니다.
이전 포스팅에서 사용한 패턴에서는 [0-9A-Fa-f]를 여섯 번 반복했는데, 이번에는 이 패턴 대신 [[:xdigit]]을 여섯 번 반복했습니다. 결과는 동일합니다.
여기서 사용한 정규표현식이 '[['로 시작해서 ']]'로 끝남에 유의합니다. 이는 POSIX 클래스를 사용할 때 매우 중요하고, 필수적입니다. POSIX 클래스는 '[:'로 시작해 ':]'로 끝나기 때문에 여기서 사용한 POSIX 문법은 ':xdigit'이 아닌 '[:xdigit]' 입니다. 따라서 바깥에 있는 대괄호는 집합을 정의하고, 안에 있는 대괄호는 POSIX 클래스 자체를 나타내는 부분입니다.
위의 표에서 나열한 POSIX 클래스 12개는 일반적으로 이를 지원하는 모든 구현에서 동작합니다. 다만, 동작 방식에 사소한 차이가 있기도 합니다.
'프로그래밍 > 정규표현식' 카테고리의 다른 글
[REGEX] 하위 표현식 (Subexpression) (0) | 2022.04.08 |
---|---|
[REGEX] 위치 찾기 (Position Matching) (0) | 2022.04.07 |
[REGEX] 반복 찾기 (0) | 2022.04.06 |
[REGEX] 문자 집합으로 찾기 (0) | 2022.04.04 |
[REGEX] 문자 하나 찾기 (0) | 2022.04.03 |
댓글