정규식
이전에 정규식을 다뤄 본 경험이 없으면 용어와 개념이 익숙하지 않겠지만 생각처럼 생소하지는 않을 것입니다.
하드 디스크에서 파일을 검색하는 방법에 대해 생각해 보십시오. 대부분의 경우 ? 및 * 문자를 사용하여 파일을 찾습니다. ? 문자는 파일 이름에서 문자 하나를 찾는 반면 *는 0개 이상의 문자를 찾습니다.
예를 들어, 'data?.dat'와 같은 패턴은 다음과 같은 파일을 찾습니다.
data1.dat
data2.dat
datax.dat
dataN.dat
? 문자 대신 * 문자를 사용하면 좀 더 많은 파일을 찾게 됩니다. 'data*.dat'는 다음과 같은 파일을 찾습니다.
data.dat
data1.dat
data2.dat
data12.dat
datax.dat
dataXYZ.dat
이러한 파일 검색 방법은 매우 유용하지만 제한되어 있습니다. ? 및 * 와일드카드 문자의 제한된 기능으로 정규식의 기능을 짐작할 수 있지만 정규식은 훨씬 더 강력하고 융통성이 있습니다.
정규식의 기원
정규식의 기원을 추적해 보면 인간 신경계의 작용 방법에 대한 초기 연구로까지 올라갑니다. 신경 생리학자인 Warren McCulloch와 Walter Pitts는 이러한 신경계를 설명할 수 있는 수학적 방법을 개발했습니다.
1956년 미국 수학자인 Stephen Kleene은 McCulloch와 Pitts의 초기 연구를 기반으로 정규식의 개념을 소개한 Representation of Events in Nerve Nets라는 논문을 발표했습니다. 그가 "정규 집합의 대수학"이라고 표현한 것을 설명하는 용어가 "정규식"입니다.
그 이후로 그의 연구는 Unix의 핵심 개발자인 Ken Thompson이 만든 초기 계산 검색 알고리즘에 적용되었습니다. 그러나 정규식이 실제로 적용된 최초의 응용 프로그램은 qed라는 Unix 편집기였습니다.
그리고 그 나머지는 말 그대로 옛날 이야기입니다. 정규식은 그 후 텍스트 기반 편집기 및 검색 도구에서 중요한 부분을 차지하게 되었습니다.
정규식 사용
일반적인 찾기 및 바꾸기 작업에서 찾을 문자열을 정확하게 입력해야 합니다. 이 기술은 정적 텍스트에서 이루어지는 간단한 찾기 및 바꾸기 작업에는 적합하지만, 융통성이 부족하며 동적 텍스트에서는 찾기 작업을 수행하기가 어렵다는 단점이 있습니다.
정규식을 통해 다음을 수행할 수 있습니다.
문자열에 있는 패턴을 테스트합니다. 예를 들어, 입력 문자열을 테스트하여 전화 번호 패턴 또는 신용 카드 번호 패턴이 문자열에 있는지 볼 수 있습니다. 이를 데이터 유효성이라고 합니다.
텍스트를 바꿉니다. 정규식을 사용하여 문서에서 특정 텍스트를 식별하고 이를 완전히 제거하거나 다른 텍스트로 바꿀 수 있습니다.
패턴 일치를 기반으로 문자열에서 부분 검색 문자열을 추출합니다. 문서 또는 입력 필드에서 특정 텍스트를 찾을 수 있습니다. 예를 들어, 전체 웹 사이트를 검색하여 오래된 자료를 제거하고 일부 HTML 서식 태그를 바꿔야 할 경우 정규식을 사용하면 찾는 자료 또는 HTML 서식 태그가 특정 파일에 있는지 여부를 테스트할 수 있습니다. 이 방법을 사용하면 영향을 받는 파일의 범위를 제거되었거나 변경된 내용이 있는 파일로 좁힐 수 있습니다. 그런 다음 정규식을 사용하여 오래된 자료를 제거하고 대체할 태그를 찾아서 바꿀 수 있습니다.
문자열 처리 기능이 지원되지 않는 언어에서도 정규식을 유용하게 사용할 수 있습니다. Visual Basic에 포함된 VBScript에는 다양한 문자열 처리 기능이 있는 반면 JScript에는 C와 마찬가지로 이러한 기능이 없습니다. 정규식은 JScript의 문자열 처리 기능을 상당히 향상시켰을 뿐만 아니라, 단일 식에서 여러 문자열을 처리할 수 있으므로 VBScript에서도 효율적으로 사용할 수 있습니다.
정규식 구문
정규식은 일반 문자(예: a에서 z)와 메타문자로 알려진 특수 문자로 구성된 텍스트 패턴입니다. 패턴은 텍스트 본문을 검색할 때 일치하는 문자열을 하나 이상 설명합니다. 정규식은 검색되는 문자열과 일치하는 문자 패턴을 찾는 템플릿의 역할을 합니다.
일반적으로 볼 수 있는 몇 가지 정규식 예는 다음과 같습니다.
JScript VBScript 검색
/^\[ \t]*$/ "^\[ \t]*$" 빈 줄을 찾습니다.
/\d{2}-\d{5}/ "\d{2}-\d{5}" 2자리, 하이픈 및 5자리로 구성된 ID 번호를 찾습니다.
/<(.*)>.*<\/\1>/ "<(.*)>.*<\/\1>" HTML 태그를 찾습니다.
아래는 정규식 컨텍스트에 사용되는 모든 메타문자와 메타문자의 동작을 보여줍니다.
문자 설명
\ 그 다음 문자를 특수 문자, 리터럴, 역참조, 또는 8진수 이스케이프로 표시합니다. 예를 들어, 'n'은 문자 "n"을 찾
고 '\n'은 줄 바꿈 문자를 찾습니다. '\\' 시퀀스는 "\"를 찾고 '\('는 "("를 찾습니다.
^ 입력 문자열의 시작 위치를 찾습니다. Multiline 속성이 설정되어 있으면 ^는 '\n' 또는 '\r'앞의 위치를 찾습니
다.
$ 입력 문자열의 끝 위치를 찾습니다. Multiline 속성이 설정되어 있으면 $는 '\n' 또는 '\r'뒤의 위치를 찾습니다.
* 부분식의 선행 문자를 0개 이상 찾습니다. 예를 들어, 'zo*'는 "z", "zoo" 등입니다. *는 {0,}와 같습니다.
+ 부분식의 선행 문자를 한 개 이상 찾습니다. 예를 들어, 'zo+'는 "zo", "zoo" 등이지만 "z"는 아닙니다. +는 {1,}와
같습니다.
? 부분식의 선행 문자를 0개 또는 한 개 찾습니다. 예를 들어, "do(es)?"는 "do" 또는 "does"의 "do"를 찾습니다. ?
는 {0,1}과 같습니다.
{n} n은 음이 아닌 정수입니다. 정확히 n개 찾습니다. 예를 들어, 'o{2}'는 "Bob"의 "o"는 찾지 않지만 "food"의 o 두
개는 찾습니다.
{n,} n은 음이 아닌 정수입니다. 정확히 n개 이상을 찾습니다. 예를 들어, 'o{2,}'는 "Bob"의 "o"는 찾지 않지만
"foooood"의 모든 o는 찾습니다. 'o{1,}'는 "o+"와 같고, 'o{0,}'는 "o*"와 같습니다.
{n,m} m과 n은 음이 아닌 정수입니다. 여기서 m은 n보다 크거나 같습니다. 최소 n개, 최대 m개 찾습니다. 예를 들어,
"o{1,3}"은 "fooooood"의 처음 세 개의 o를 찾습니다. "o{0,1}"은 "o?"와 같습니다. 쉼표와 숫자 사이에는 공백을
넣을 수 없습니다.
? 이 문자가 다른 한정 부호(*, +, ?, {n}, {n,}, {n,m})의 바로 뒤에 나올 경우 일치 패턴은 제한적입니다. 기본값인
무제한 패턴은 가능한 많은 문자열을 찾는 데 반해 제한적인 패턴은 가능한 적은 문자열을 찾습니다. 예를 들어,
"oooo" 문자열에서 "o+?"는 "o" 한 개만 찾고, "o+"는 모든 "o"를 찾습니다.
. "\n"을 제외한 모든 단일 문자를 찾습니다. "\n"을 포함한 모든 문자를 찾으려면 '[.\n]' 패턴을 사용하십시오.
(pattern) pattern을 찾아 검색한 문자열을 캡처합니다. 캡처한 문자열은 VBScript의 경우 SubMatches 컬렉션, Jscript의 경
우 $0...$9 속성을 이용하여 결과로 나오는 Matches 컬렉션에서 추출할 수 있습니다. 괄호 문자인 ( )를 찾으려면
"\(" 또는 "\)"를 사용하십시오.
(?:pattern) pattern을 찾지만 검색한 문자열을 캡처하지 않습니다. 즉, 검색한 문자열을 나중에 사용할 수 있도록 저장하지
않는 비캡처 검색입니다. 이것은 패턴의 일부를 "or" 문자(|)로 묶을 때 유용합니다. 예를 들어, 'industr(?:y|ies)
는 'industry|industries'보다 더 경제적인 식입니다.
(?=pattern) 포함 예상 검색은 pattern과 일치하는 문자열이 시작하는 위치에서 검색할 문자열을 찾습니다. 이것은 검색한 문
자열을 나중에 사용할 수 있도록 캡처하지 않는 비캡처 검색입니다. 예를 들어, "Windows(?=95|98|NT|2000)"는
"Windows 2000"의 "Windows"는 찾지만 "Windows 3.1"의 "Windows"는 찾지 않습니다. 예상 검색은 검색할 문자
열을 찾은 후 예상 검색 문자열을 구성하는 문자 다음부터가 아니라 마지막으로 검색한 문자열 바로 다음부터 찾
기 시작합니다.
(?!pattern) 제외 예상 검색은 pattern과 일치하지 않는 문자열이 시작하는 위치에서 검색할 문자열을 찾습니다. 이것은 검색
한 문자열을 나중에 사용할 수 있도록 캡처하지 않는 비캡처 검색입니다. 예를 들어,
"Windows(?!95|98|NT|2000)"는 "Windows 3.1"의 "Windows"는 찾지만 "Windows 2000"의 "Windows"는 찾지 않습
니다. 예상 검색은 검색할 문자열을 찾은 후 예상 검색 문자열을 구성하는 문자 다음부터가 아니라 마지막으로
검색한 문자열 바로 다음부터 찾기 시작합니다.
x|y x 또는 y를 찾습니다. 예를 들어, "z|food"는 "z" 또는 "food"를 찾습니다. "(z|f)ood"는 "zood" 또는 "food"를 찾습니
다.
[xyz] 문자 집합입니다. 괄호 안의 문자 중 하나를 찾습니다. 예를 들어, "[abc]"는 "plain"의 "a"를 찾습니다.
[^xyz] 제외 문자 집합입니다. 괄호 밖의 문자 중 하나를 찾습니다. 예를 들어, "[^abc]"는 "plain"의 "p"를 찾습니다.
[a-z] 문자 범위입니다. 지정한 범위 안의 문자를 찾습니다. 예를 들어, "[a-z]"는 "a"부터 "z" 사이의 모든 소문자를 찾
습니다.
[^a-z] 제외 문자 범위입니다. 지정된 범위 밖의 문자를 찾습니다. 예를 들어, "[^a-z]"는 "a"부터 "z" 사이에 없는 모든
문자를 찾습니다.
\b 단어의 경계, 즉 단어와 공백 사이의 위치를 찾습니다. 예를 들어, "er\b"는 "never"의 "er"는 찾지만 "verb"의
"er"는 찾지 않습니다.
\B 단어의 비경계를 찾습니다. "er\B"는 "verb"의 "er"는 찾지만 "never"의 "er"는 찾지 않습니다.
\cx X 가 나타내는 제어 문자를 찾습니다. 예를 들어, \cM은 Control-M 즉, 캐리지 리턴 문자를 찾습니다. x 값은
A-Z 또는 a-z의 범위 안에 있어야 합니다. 그렇지 않으면 c는 리터럴 "c" 문자로 간주됩니다.
\d 숫자 문자를 찾습니다. [0-9]와 같습니다.
\D 비숫자 문자를 찾습니다. [^0-9]와 같습니다.
\f 폼피드 문자를 찾습니다. \x0c와 \cL과 같습니다.
\n 줄 바꿈 문자를 찾습니다. \x0a와 \cJ와 같습니다.
\r 캐리지 리턴 문자를 찾습니다. \x0d와 \cM과 같습니다.
\s 공백, 탭, 폼피드 등의 공백을 찾습니다. "[ \f\n\r\t\v]"와 같습니다.
\S 공백이 아닌 문자를 찾습니다. "[^ \f\n\r\t\v]"와 같습니다.
\t 탭 문자를 찾습니다. \x09와 \cI와 같습니다.
\v 수직 탭 문자를 찾습니다. \x0b와 \cK와 같습니다.
\w 밑줄을 포함한 모든 단어 ?美?찾습니다. "[A-Za-z0-9_]"와 같습니다.
\W 모든 비단어 문자를 찾습니다. "[^A-Za-z0-9_]"와 같습니다.
\xn n을 찾습니다. 여기서 n은 16진수 이스케이프 값입니다. 16진수 이스케이프 값은 정확히 두 자리여야 합니다. 예
를 들어, '\x41'은 "A"를 찾고 '\x041'은 '\x04'와 "1"과 같습니다. 정규식에서 ASCII 코드를 사용할 수 있습니다.
\num num을 찾습니다. 여기서 num은 양의 정수입니다. 캡처한 문자열에 대한 역참조입니다. 예를 들어, '(.)\1'은 연속
적으로 나오는 동일한 문자 두 개를 찾습니다.
\n 8진수 이스케이프 값이나 역참조를 나타냅니다. \n 앞에 최소한 n개의 캡처된 부분식이 나왔다면 n은 역참조입
니다. 그렇지 않은 경우 n이 0에서 7 사이의 8진수이면 n은 8진수 이스케이프 값입니다.
\nm 8진수 이스케이프 값이나 역참조를 나타냅니다. \nm 앞에 최소한 nm개의 캡처된 부분식이 나왔다면 nm은 역참
조입니다. \nm 앞에 최소한 n개의 캡처가 나왔다면 n은 역참조이고 뒤에는 리터럴 m이 옵니다. 이 두 경우가 아
닐 때 n과 m이 0에서 7 사이의 8진수이면 \nm은 8진수 이스케이프 값 nm을 찾습니다.
\nml n이 0에서 3 사이의 8진수이고 m과 l이 0에서 7 사이의 8진수면 8진수 이스케이프 값 nml을 찾습니다.
\un n은 4 자리의 16진수로 표현된 유니코드 문자입니다. 예를 들어, \u00A9는 저작권 기호(©)를 찾습니다.
정규식 만들기
정규식은 산술식을 만드는 것과 같은 방법으로 구성됩니다. 즉, 작은 식은 다양한 메타문자 및 연산자를 사용하여 결합되며 이는 더 큰 식을 만듭니다.
한 쌍의 구분 기호 안에 식 패턴의 다양한 구성 요소를 넣어서 정규식을 구성합니다. JScript에서 구분 기호는 한 쌍의 슬래시(/) 문자입니다. 예를 들어 다음과 같습니다.
/expression/
VBScript에서는 한 쌍의 따옴표("")로 정규식을 구분합니다. 예를 들어 다음과 같습니다.
"expression"
위의 두 예제에서 정규식 패턴(expression)은 RegExp 개체의 Pattern 속성에 저장됩니다.
정규식의 구성 요소는 개별 문자, 문자 집합, 문자 범위, 문자 간 선택 또는 이러한 모든 구성 요소의 조합일 수 있습니다.
우선 순위
일단 정규식을 구성하면 산술식처럼 평가됩니다. 즉, 왼쪽에서 오른쪽으로 평가되고 우선 순위에 따라 이루어집니다.
아래 표는 다양한 정규식 연산자의 우선 순위를 가장 높은 것에서 가장 낮은 것까지 보여줍니다.
연산자 설명
\ 이스케이프
(), (?:), (?=), [] 괄호 및 대괄호
*, +, ?, {n}, {n,}, {n,m} 한정 기호
^, $, \anymetacharacter 앵커 및 시퀀스
| 대체
일반 문자
일반 문자는 명시적으로 메타문자로 지정되지 않은 인쇄할 수 있는 문자 및 인쇄할 수 없는 문자로 구성됩니다. 여기에는 모든 대소문자, 모든 숫자, 모든 구두점 및 일부 기호가 포함됩니다.
가장 간단한 정규식 양식은 검색된 문자열에서 문자 자체를 찾는 단일 일반 문자입니다. 예를 들어, 단일 문자 패턴 'A'는 검색된 문자열에 나타날 때마다 'A' 문자를 찾습니다. 단일 문자 정규식 패턴의 몇 가지 예는 다음과 같습니다.
/a/
/7/
/M/
이와 동일한 VBScript 단일 문자 정규식은 다음과 같습니다.
"a"
"7"
"M"
여러 개의 단일 문자를 결합하여 좀 더 큰 식을 만들 수 있습니다. 예를 들어, 다음 JScript 정규식은 단일 문자 식인 'a', '7' 및 'M'을 결합하여 만들어진 식입니다.
/a7M/
이와 동일한 VBScript 식은 다음과 같습니다.
"a7M"
여기에는 연결 연산자가 필요하지 않으며 문자를 하나씩 나열하기만 하면 됩니다.
특수 문자
문자열을 찾을 때 특별히 처리해야 하는 여러 가지 메타문자가 있습니다. 이러한 특수 문자를 찾으려면 먼저 이를 이스케이프해야 합니다. 즉, 특수 문자 앞에 백슬래시 문자(\)를 입력해야 합니다. 다음 표는 특수 문자와 그 의미를 보여줍니다.
특수 문자 설명
$ 입력 문자열의 끝 위치를 찾습니다. RegExp 개체의 Multiline 속성이 설정되어 있으면 $는 '\n' 또는 '\r' 앞의 위
치를 찾습니다. $ 문자 자체를 찾으려면 \$를 사용하십시오.
( ) 부분식의 시작과 끝을 찾습니다. 부분식은 나중에 사용할 수 있도록 캡처할 수 있습니다. 이 문자를 찾으려면
\( 및 \)를 사용하십시오.
* 부분식의 선행 문자를 0개 이상 찾습니다. * 문자를 찾으려면 \*를 사용하십시오.
+ 부분식의 선행 문자를 한 개 이상 찾습니다. + 문자를 찾으려면 \+를 사용하십시오.
. 줄 바꿈 문자 \n을 제외한 모든 단일 문자를 찾습니다. .를 찾으려면 \.를 사용하십시오.
[ 대괄호 식의 시작 위치를 찾습니다. [를 찾으려면 \[를 사용하십시오.
? 부분식의 선행 문자를 0개 또는 한 개 찾거나 제한적인 한정 기호를 나타냅니다. ?를 찾으려면 \?를 사용하십시
오.
\ 그 다음 문자를 특수 문자, 리터럴, 역참조 또는 8진수 이스케이프로 표시합니다. 예를 들어, 'n'은 문자 'n'을 찾
고 '\n'은 줄 바꿈 문자를 찾습니다. '\\' 시퀀스는 "\"를 찾고 '\('는 "("를 찾습니다.
^ 입력 문자열의 시작 위치를 찾습니다. 대괄호 식에서 사용될 때는 대괄호에 포함된 문자 집합을 제외한 문자열을
찾습니다. ^ 문자 자체를 찾으려면 \^를 사용하십시오.
{ 한정 기호 식의 시작 위치를 찾습니다. {를 찾으려면 \{를 사용하십시오.
| 두 항목 간의 선택을 나타냅니다. |를 찾으려면 \|를 사용하십시오.
인쇄할 수 없는 문자
가끔 사용하는 문자 중 인쇄할 수 없는 유용한 문자가 여러 개 있습니다. 아래 표에서는 인쇄할 수 없는 이들 문자를 나타낼 때 사용되는 이스케이프 시퀀스를 보여줍니다.
문자 의미
\cx x가 나타내는 제어 문자를 찾습니다. 예를 들어, \cM은 Control-M 즉, 캐리지 리턴 문자를 찾습니다. x 값은 A-
Z 또는 a-z의 범위 안에 있어야 합니다. 그렇지 않으면 c는 리터럴 "c" 문자로 간주됩니다.
\f 폼피드 문자를 찾습니다. \x0c와 \cL과 같습니다.
\n 줄 바꿈 문자를 찾습니다. \x0a와 \cJ와 같습니다.
\r 캐리지 리턴 문자를 찾습니다. \x0d와 \cM과 같습니다.
\s 공백, 탭, 폼피드 등의 공백을 찾습니다. "[ \f\n\r\t\v]"와 같습니다.
\S 공백이 아닌 문자를 찾습니다. "[^ \f\n\r\t\v]"와 같습니다.
\t 탭 문자를 찾습니다. \x09와 \cI와 같습니다.
\v 수직 탭 문자를 찾습니다. \x0b와 \cK와 같습니다.
문자 일치
마침표(.)는 문자열에서 줄 바꿈 문자(\n)를 제외한 단일 인쇄 또는 비인쇄 문자를 찾습니다. 다음 JScript 정규식은 'aac', 'abc', 'acc', 'adc' 뿐만 아니라 'a1c', 'a2c', a-c' 및 a#c'를 나타내기도 합니다.
/a.c/
이와 동일한 VBScript 정규식은 다음과 같습니다.
"a.c"
입력 문자열의 일부에 마침표(.)가 있는 파일 이름이 포함된 문자열을 찾을 경우 정규식에서 마침표 앞에 백슬래시(\) 문자를 입력하십시오. 예를 들어 다음 JScript 정규식은 'filename.ext'를 찾습니다.
/filename\.ext/
이와 동일한 VBScript 식은 다음과 같습니다.
"filename\.ext"
이러한 식은 제한적이어서 여기서는 임의의 단일 문자만 찾을 수 있습니다. 그러나 목록에서 지정된 문자를 찾을 경우 유용합니다. 예를 들어, Chapter 1, Chapter 2 등과 같이 숫자로 표시된 장 제목이 들어 있는 입력 텍스트가 있을 때 이러한 장 제목을 찾을 수 있습니다.
대괄호 식
하나 이상의 개별 문자를 대괄호([ ]) 안에 입력하여 찾을 문자 목록을 만들 수 있습니다. 문자를 대괄호로 묶으면 목록은 대괄호 식이 됩니다. 다른 곳에서와 마찬가지로 대괄호 안에서 일반 문자는 문자 자체를 나타내므로 입력 텍스트에서 문자 자체를 찾지만 대괄호 식에서 대부분의 특수 문자는 문자 자체를 찾지 않습니다. 다음은 몇 가지 예외입니다.
']' 문자는 목록의 첫째 항목이 아닌 경우 이 목록을 종료합니다. 목록에서 ']' 문자 자체를 찾으려면 이를 '[' 바로 다음에 놓으십시오.
'\' 문자는 계속 이스케이프 문자로 사용됩니다. '\' 문자를 찾으려면 '\\'를 사용하십시오.
대괄호 식으로 묶인 문자는 대괄호 식이 나타나는 정규식의 위치에 해당하는 단일 문자만을 찾습니다. 다음 JScript 정규식은 'Chapter 1', 'Chapter 2', 'Chapter 3', 'Chapter 4' 및 'Chapter 5' 등을 검색합니다.
/Chapter [12345]/
VBScript에서 위와 같은 장 제목을 찾으려면 다음을 사용하십시오.
"Chapter [12345]"
단어 'Chapter' 및 이어지는 공백은 대괄호 내에 있는 문자와 관련된 위치에 고정됩니다. 그러면 대괄호 식은 단어 'Chapter' 및 공백 바로 다음에 오는 단일 문자 위치에 해당하는 문자 집합만 지정하므로 여기서는 아홉 번째 문자 위치입니다.
문자 자체 대신 범위를 사용하여 검색 문자를 표현하려면 하이픈 문자(-)를 사용하여 시작하는 문자와 끝나는 문자를 구분합니다. 개별 문자의 문자 값은 범위에서의 상育?순서를 결정합니다. 다음 JScript 정규식에는 위의 대괄호로 묶인 목록과 같은 범위식이 들어 있습니다.
/Chapter [1-5]/
이와 동일한 VBScript의 식은 다음과 같습니다.
"Chapter [1-5]"
범위가 이러한 방식으로 지정되면 시작하는 값과 끝나는 값이 범위에 포함됩니다. 시작하는 값은 유니코드 정렬 순서에서 끝나는 값 앞에 와야 합니다.
대괄호 식에 하이픈 문자를 포함시켜려면 다음 중 하나를 수행해야 합니다.
백슬래시로 이스케이프합니다.
[\-]
대괄호로 묶은 목록의 시작 또는 끝에 하이픈 문자를 놓습니다. 다음 식은 모든 소문자 및 하이픈을 찾습니다.
[-a-z]
[a-z-]
시작하는 문자 값이 하이픈보다 먼저 오고, 끝나는 문자 값이 하이픈과 같거나 하이픈보다 나중에 오도록 범위를 만듭니다. 다음 두 정규식은 모두 이 요구 사항을 만족합니다.
[!--]
[!-~]
목록 시작에 캐럿(^) 문자를 놓으면 목록이나 범위에 없는 모든 문자를 찾을 수도 있습니다. 목록에서 캐럿 문자가 다른 위치에 나타나면 이는 특별한 의미 없이 캐럿 문자 자체를 찾습니다. 다음 JScript 정규식은 장 제목의 숫자가 5보다 큰 경우를 찾습니다.
/Chapter [^12345]/
VBScript에서 사용하는 경우는 다음과 같습니다.
"Chapter [^12345]"
위의 예제에서 식은 1, 2, 3, 4, 5를 제외하고 9번째 위치에 있는 모든 숫자 문자를 찾습니다. 예를 들어, 'Chapter 7'과 'Chapter 9'를 찾습니다.
하이픈 문자(-)를 사용하여 위와 동일한 식을 나타낼 수 있습니다. JScript의 경우는 다음과 같습니다.
/Chapter [^1-5]/
VBScript의 경우는 다음과 같습니다.
"Chapter [^1-5]"
일반적으로 대괄호 식은 대소문자 또는 숫자 검색을 지정하기 위해 사용됩니다. 다음 JScript 식은 이러한 검색을 지정합니다.
/[A-Za-z0-9]/
이와 동일한 VBScript의 식은 다음과 같습니다.
"[A-Za-z0-9]"
한정 기호
검색 문자가 몇 개인지 모를 때도 있습니다. 이러한 불확실성을 해결하기 위해 정규식에서는 한정 기호의 개념을 지원합니다. 이러한 한정 기호를 사용하면 정규식에서 지정된 구성 요소가 몇 개 나타나야 검색이 참이 되는지를 지정할 수 있습니다.
아래 표에서는 다양한 한정 기호 및 그 의미를 설명합니다.
문자 설명
* 부분식의 선행 문자를 0개 이상 찾습니다. 예를 들어, 'zo*'는 "z" 와 "zoo"를 찾습니다. *는 {0,}와 같습니다.
+ 부분식의 선행 문자를 한 개 이상 찾습니다. 예를 들어, 'zo+'는 "zo" 및 "zoo"는 찾지만 "z"는 검색하지는 않습니
다. +는 {1,}와 같습니다.
? 부분식의 선행 문자를 0개 이상 찾습니다. 예를 들어, 'do(es)?'는 "do" 또는 "does"의 "do"를 찾습니다. ?는 {0,1}
과 같습니다.
{n} n은 음이 아닌 정수입니다. 정확하게 n 개 찾습니다. 예를 들어, 'o{2}'는 "Bob"의 'o'는 찾지 않지만 "food"의 o 두
개는 찾습니다.
{n,} n은 음이 아닌 정수입니다. 최소한 n 개 찾습니다. 예를 들어, 'o{2,}'는 "Bob"의 'o'는 찾지 않고 "foooood"의 o는
모두 찾습니다. 'o{1,}'는 'o+'와 같고 'o{0,}'는 'o*'와 같습니다.
{n,m} m 및 n은 음이 아닌 정수며 여기서 n <= m입니다. 최소한 n 개, 최대한 m개 찾습니다. 예를 들어, 'o{1,3}'은
"fooooood"의 처음 o 세 개를 찾습니다. 'o{0,1}'은 'o?'와 같습니다. 쉼표와 숫자 사이에는 공백을 넣을 수 없습니
다.
입력 문서가 큰 경우 장 번호는 9를 넘기 쉬우므로 두 자리 또는 세 자리 수의 장 번호를 처리할 수 있는 방법이 필요합니다. 한정 기호는 이러한 기능을 제공합니다. 다음 JScript 정규식은 모든 자리 수의 장 제목을 찾습니다.
/Chapter [1-9][0-9]*/
이와 동일한 VBScript 정규식은 다음과 같습니다.
"Chapter [1-9][0-9]*"
한정 기호는 범위식 다음에 나타납니다. 그러므로 이 경우 한정 기호는 0과 9를 포함한 자리 수를 지정하는 전체 범위식에 적용됩니다.
'+' 한정 기호는 두 번째 위치 또는 그 다음에 꼭 숫자가 올 필요가 없으므로 여기서 사용되지 않습니다. '?' 문자도 장 번호를 두 자리 수로 제한하므로 사용되지 않습니다. 'Chapter'와 공백 문자 다음에 한 자리 수 이상을 찾을 수도 있습니다.
장 번호는 99장으로만 제한되므로 다음 JScript 식을 사용하여 적어도 한 자리 수를 지정할 수 있지만 두 자리 수 이상은 지정할 수 없습니다.
/Chapter [0-9]{1,2}/
VBScript의 경우 다음 정규식을 사용하십시오.
"Chapter [0-9]{1,2}"
위 식의 단점은 99보다 큰 장 번호가 있어도 처음 두 자리 수에 해당하는 장 번호만을 찾는다는 것입니다. 또한 누군가가 Chapter 0을 만들어도 그것까지 찾습니다. 두 자리 수만을 찾는 JScript 식은 아래 예를 사용하는 것이 좋습니다.
/Chapter [1-9][0-9]?/
또는 다음을 사용합니다.
/Chapter [1-9][0-9]{0,1}/
이와 동일한 VBScript 식은 다음과 같습니다.
"Chapter [1-9][0-9]?"
또는 다음과 같습니다.
"Chapter [1-9][0-9]{0,1}"
'*', '+' 및 '?' 한정 기호는 모두 무제한적이라고 하며 가능한 한 텍스트를 많이 찾습니다. 그러나 이렇게 많이 찾을 필요가 없는 경우도 있습니다. 즉, 최소한으로 찾아야 하는 경우도 있습니다.
예를 들어, HTML 문서에 다음과 같은 텍스트가 있고, H1 태그로 묶인 장 제목을 찾는다고 가정합니다.
<H1>Chapter 1 – Introduction to Regular expressions</H1>
다음 식은 여는 H1 태그에 있는 보다 작음 기호(<)에서 닫는 H1 태그 끝에 있는 보다 큼 기호(>) 사이에 있는 모든 문자열을 찾습니다.
/<.*>/
VBScript 정규식은 다음과 같습니다.
"<.*>"
실제 검색하려는 문자열이 여는 H1 태그뿐인 경우에 다음 제한적인 식은 <H1>만 찾습니다.
/<.*?>/
또는 다음과 같이 나타냅니다.
"<.*?>"
'?'를 '*', '+' 또는 '?' 한정 기호 다음에 놓으면 식은 무제한적인 검색에서 제한적인 검색 또는 최소 검색으로 변환됩니다.
앵커
지금까지 예는 장 제목이 나타나는 위치를 찾는 작업에 관한 것이었습니다. 공백, 숫자가 이어지는 'Chapter' 문자열의 위치는 실제 장 제목이거나 다른 장에 대한 상호 참조일 수 있습니다. 실제로 장 제목은 항상 줄의 시작 위치에 있으므로 제목만 찾고 상호 참조는 찾지 않는 방법을 만들 수 있습니다.
앵커가 이러한 기능을 제공합니다. 앵커를 사용하면 정규식을 줄의 시작이나 끝으로 고정시킬 수 있습니다. 단어 내부 또는 단어 시작이나 끝에 나타나는 정규식을 만들 수도 있습니다. 다음 표는 정규식 앵커 및 그 의미를 보여줍니다.
문자 설명
^ 입력 문자열의 시작 위치를 찾습니다. Multiline 속성이 설정되어 있으면 ^는 '\n' 또는 '\r'앞의 위치를 찾습니다.
$ 입력 문자열의 끝 위치를 찾습니다. Multiline 속성이 설정되어 있으면 $는 '\n' 또는 '\r'뒤의 위치를 찾습니다.
\b 단어의 경계, 즉 단어와 공백 사이의 위치를 찾습니다. 예를 들어, 'er\b'는 "never"의 "er"는 찾지만 "verb"의
"er"는 찾지 않습니다.
\B 단어의 비경계를 찾습니다. 'er\B'는 "verb"의 "er"는 찾지만 "never"의 "er"는 찾지 않습니다.
앵커와 한정 기호는 함께 사용할 수 없습니다. 줄 바꿈 또는 단어 경계 전후 바로 다음에는 한 자리만 올 수 있으므로 '^*'와 같은 식은 허용되지 않습니다.
텍스트 줄의 시작 위치에 있는 텍스트를 찾으려면 정규식 시작에 '^' 문자를 사용합니다. 이것은 대괄호 식에서 사용하는 '^'와는 다릅니다.
텍스트 줄 끝에 있는 텍스트를 찾으려면 정규식 끝에 '$' 문자를 사용하십시오.
장 제목을 찾을 때 다음 JScript 정규식에서처럼 앵커를 사용할 수 있습니다. 그러면 줄의 시작 위치에서 두 자리까지 장 제목을 찾습니다.
/^Chapter [1-9][0-9]{0,1}/
이와 동일한 VBScript의 정규식은 다음과 같습니다.
"^Chapter [1-9][0-9]{0,1}"
실제로 장 제목이 있는 줄에는 장 제목만 있으므로 장 제목은 줄의 시작 및 끝에 있어야 합니다. 다음 식에서 지정된 검색 문자열은 장만 찾고 상호 참조는 찾지 않습니다. 따라서 이 정규식은 텍스트 줄의 시작과 끝에서만 찾습니다.
/^Chapter [1-9][0-9]{0,1}$/
VBScript 를 사용하는 경우는 다음과 같습니다.
"^Chapter [1-9][0-9]{0,1}$"
단어 경계를 찾는 방법은 약간 다르지만 정규식에 매우 중요한 기능을 추가합니다. 단어 경계는 단어와 공백 사이의 위치입니다. 비단어 경계는 그외 다른 위치입니다. 다음 JScript 식은 단어 'Chapter'의 처음 세 문자가 단어 경계 다음에 나타나므로 이 세 문자를 찾습니다.
/\bCha/
또는 VBScript의 경우는 다음과 같습니다.
"\bCha"
여기서 '\b' 연산자의 위치는 매우 중요합니다. 이 연산자가 검색할 문자열 앞에 올 경우 단어의 시작 부분에서 문자열을 찾고 검색할 문자열 뒤에 올 경우에는 단어의 끝 부분에서 문자열을 찾습니다. 예를 들어, 다음 식은 'ter'가 단어 경계 앞에 오므로 'Chapter'라는 단어에서 'ter'를 찾습니다.
/ter\b/
또는 다음과 같습니다.
"ter\b"
다음 식은 'Chapter'의 'apt'를 찾지만 'aptitude'의 'apt는 찾지 않습니다.
/\Bapt/
또는 다음과 같습니다.
"\Bapt"
왜냐하면 'apt'는 'Chapter'라는 단어에서 비단어 경계에 있지만 'aptitude'라는 단어에서는 단어 경계에 있기 때문입니다. 비단어 경계 연산자의 경우 검색할 문자열이 단어 시작이나 끝과 관계가 없으므로 위치는 중요하지 않습니다.
대체 및 그룹화
대체 정규식은 '|' 문자를 사용하여 두 개 이상의 대안 중 하나를 선택할 수 있습니다. 또한 장 제목 정규식을 확장하여 장 제목 이상의 것을 다루도록 할 수도 있으나 생각처럼 그리 간단하지는 않습니다. 대체 정규식을 사용하면 '|' 문자 양쪽의 식 중 가능한 가장 큰 식을 찾습니다. 다음 JScript 및 VBScript의 식이 줄의 시작과 끝에서 'Chapter' 또는 'Section' 다음에 한 자리 또는 두 자리 수가 나오는 문자열을 찾는다고 생각할 수 있습니다.
/^Chapter|Section [1-9][0-9]{0,1}$/
"^Chapter|Section [1-9][0-9]{0,1}$"
하지만 위의 정규식은 줄 첫부분에 나오는 'Chapter' 또는 줄 끝에 나오는 'Section'과 다음에 모든 수가 오는 경우를 찾습니다. 입력 문자열이 'Chapter 22'일 경우 위의 식은 단어 'Chapter'만 찾고 입력 문자열이 'Section 22'일 경우 식은 'Section 22'를 찾습니다. 그러나 이 정규식은 의도했던 것과는 다르므로 사용자의 의도에 맞는 결과가 나올 수 있는 정규식을 만들어 보겠습니다.
괄호를 사용하여 대체 범위를 제한할 수 있습니다. 즉, 두 단어 'Chapter'와 'Section'만 적용되도록 제한합니다. 그러나 나중에 부분식에 대한 절에서 설명하겠지만, 괄호는 부분식을 만들 때도 사용되므로 그 사용 방법이 까다롭습니다. 위의 정규식에서 적합한 위치에 괄호를 추가하면 'Chapter 1' 또는 'Section 3'과 같은 문자열을 찾는 정규식을 만들 수 있습니다.
다음 정규식은 괄호를 사용하여 'Chapter' 및 'Section'을 그룹화했으므로 식이 제대로 작동하게 됩니다. JScript의 경우는 다음과 같습니다.
/^(Chapter|Section) [1-9][0-9]{0,1}$/
VBScript의 경우는 다음과 같습니다.
"^(Chapter|Section) [1-9][0-9]{0,1}$"
이 식은 제대로 작동하지만 예기치 않은 결과가 발생하기도 합니다. 'Chapter|Section' 앞뒤로 괄호를 넣으면 적절하게 그룹화되고, 이 두 단어 중 하나는 나중에 사용할 수 있도록 캡처됩니다. 위의 식에는 괄호 쌍이 하나뿐이므로 부분 검색 문자열이 하나만 캡처됩니다. 이 부분 검색 문자열은 VBScript의 Submatches 컬렉션을 사용하거나 JScript에 있는 RegExp 개체의 $1-$9 속성을 사용하여 참조할 수 있습니다.
부분 검색 문자열을 캡처하는 것이 바람직할 때도 있고 그렇지 않을 때도 있습니다. 위의 예제에서 실제로 하려는 작업은 괄호를 사용하여 단어 'Chapter' 또는 'Section' 중 선택한 것을 그룹화하는 것입니다. 검색한 문자열을 나중에 참조할 필요는 없습니다. 사실, 부분 검색 문자열을 캡처할 필요가 없으면 이를 사용하지 마십시오. 그러면 정규식에서 이런 문자열을 저장하기 위해 시간과 메모리를 사용하지 않아도 되므로 효율성이 높아집니다.
괄호 안에서 정규식 패턴 앞에 ''?:'를 사용하면 나중에 사용하도록 문자열을 저장하지 않습니다. 다음 예는 위의 정규식을 수정한 것으로, 부분 검색 문자열을 저장하지 않으면서 위의 식과 동일한 기능을 합니다. JScript의 경우는 다음과 같습니다.
/^(?:Chapter|Section) [1-9][0-9]{0,1}$/
VBScript의 경우는 다음과 같습니다.
"^(?:Chapter|Section) [1-9][0-9]{0,1}$"
'?:' 메타문자 외에도 예상 검색에 사용하는 기타 비캡처 메타문자가 두 가지 있습니다. ?=로 지정된 포함 예상 검색은 괄호 안의 정규식 패턴과 일치하는 문자열이 시작되는 곳에서 문자열을 검색합니다. '?!'로 지정된 제외 예상 검색은 정규식과 일치하지 않는 문자열이 시작되는 곳에서 문자열을 검색합니다.
예를 들어, Windows 3.1, Windows 95, Windows 98 및 Windows NT에 대한 참조가 들어 있는 문서가 있습니다. Windows 95, Windows 98 및 Windows NT에 대한 모든 참조를 찾고 이러한 참조를 Windows 2000으로 변경하여 문서를 업데이트해야 한다고 가정합니다. 다음 JScript 정규식은 포함 예상 검색의 예를 보여주고 있으며 Windows 95, Windows 98 및Windows NT를 찾습니다.
/Windows(?=95 |98 |NT )/
이와 동일한 VBScript 식은 다음과 같습니다.
"Windows(?=95 |98 |NT )"
일단 문자열을 찾으면 예상 문자열에 포함된 문자를 제외하고 검색된 텍스트 바로 다음부터 찾기 시작합니다. 예를 들어, 위의 정규식이 'Windows 98'을 찾으면 '98' 다음이 아닌 'Windows' 다음부터 다시 찾습니다.
역참조
정규식의 가장 중요한 기능 중 하나는 나중에 사용하도록 검색된 패턴의 일부를 저장하는 기능입니다. 앞에서 설명했듯이 정규식 패턴 또는 패턴의 일부를 괄호로 묶으면 그 식의 일부를 임시 버퍼에 저장할 수 있습니다. 비캡처 메타문자인 '?:', '?=' 또는 '?!'를 사용하여 저장된 정규식 일부를 무시할 수 있습니다.
캡처된 각 부분 검색 문자열은 정규식 패턴에서 왼쪽에서 오른쪽으로 저장됩니다. 부분 검색 문자열이 저장되는 버퍼 번호는 1부터 시작해서 최대 99개의 부분식까지 저장할 수 있습니다. 서로 다른 버퍼는 '\n'을 사용하여 액세스할 수 있는데 여기서 n은 특정 버퍼를 식별하는 한 자리 또는 두 자리의 십진수입니다.
가장 간단하고 가장 유용한 역참조 응용 프로그램 중 하나는 텍스트에서 동일한 두 단어를 찾는 기능을 제공합니다. 다음 문장을 살펴 보십시오.
Is is the cost of of gasoline going up up?
위 문장의 문제는 단어가 중복되어 있다는 것입니다. 모든 단어마다 일일이 중복 여부를 검사하지 않고 그 문장을 수정하는 방법을 개발하면 좋을 것입니다. 다음 JScript 정규식은 단일 부분식을 사용하여 이 문제를 해결합니다.
/\b([a-z]+) \1\b/gi
이와 동일한 VBScript 식은 다음과 같습니다.
"\b([a-z]+) \1\b"
이 경우 괄호 안의 모든 요소가 부분식이 됩니다. 캡처된 식에는 '[a-z]+'에 지정된 대로 영문자를 하나 이상 포함하고 있습니다. 정규식의 두 번째 부분은 이전에 캡처된 부분 검색 문자열에 대한 참조입니다. 즉, 대괄호 식에서 검색된 단어의 두 번째 경우입니다. '\1'을 사용하여 지정된 첫 번째 觀?검색 문자열을 지정합니다. 단어 경계 메타문자는 구분된 단어만 검색합니다. 그렇게 하지 않으면 이 식에서 "is issued" 또는 "this is"와 같은 구가 제대로 식별되지 않습니다.
JScript 식에서 정규식 다음에 오는 전역 플래그('g')는 입력 문자열에서 찾을 수 있는 가능한 한 많은 검색할 문자열에 식이 적용됨을 나타냅니다. 식 끝의 대소문자 구분 안함('i') 플래그는 대소문자를 구분하지 않도록 지정합니다. 여러 줄 플래그는 줄 바꿈 문자 양쪽에 잠재적으로 검색할 문자열이 있을 수 있음을 지정합니다. VBScript에서는 식에서 여러 가지 플래그를 설정할 수는 없지만 RegExp 개체의 속성을 사용하여 명시적으로 설정할 수 있습니다.
위의 정규식을 사용하면 다음 JScript 코드로 부분 검색 문자열 정보를 사용하여 텍스트의 문자열에 연속으로 나오는 동일한 두 단어를 한 단어로 바꿀 수 있습니다.
var ss = "Is is the cost of of gasoline going up up?.\n";
var re = /\b([a-z]+) \1\b/gim; //정규식 패턴을 만듭니다.
var rv = ss.replace(re,"$1"); //두 단어를 한 단어로 바꿉니다.
이와 거의 동일한 VBScript 코드는 다음과 같습니다.
Dim ss, re, rv
ss = "Is is the cost of of gasoline going up up?." & vbNewLine
Set re = New RegExp
re.Pattern = "\b([a-z]+) \1\b"
re.Global = True
re.IgnoreCase = True
re.MultiLine = True
rv = re.Replace(ss,"$1")
VBScript 코드에서 전역 플래그, 대소문자 구분 안함 플래그 및 여러 행 플래그는 적절히 명명된 RegExp 개체의 속성을 사용하여 설정됩니다.
replace 메서드에서 $1을 사용하면 처음 저장된 부분 검색 문자열을 참조합니다. 부분 검색 문자열이 하나 이상 있으면 이를 $2, $3 등을 사용하여 계속 참조할 수 있습니다.
역참조를 사용하는 또 다른 방법은 URI(Universal Resource Indicator)를 각 구성 요소로 나누는 것입니다. 다음 URI를 프로토콜(ftp, http 등), 도메인 주소 및 페이지/경로로 나눌 수 있습니다.
http://msdn.microsoft.com:80/scripting/default.htm
다음 정규식은 그 기능을 제공합니다. JScript의 경우는 다음과 같습니다.
/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/
VBScript의 경우는 다음과 같습니다.
"(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)"
괄호로 묶은 첫 번째 부분식은 웹 주소의 프로토콜 부분을 캡처하도록 설계되었습니다. 이 부분식은 콜론과 두 개의 슬래시 앞에 오는 단어를 모두 찾습니다. 괄호로 묶은 두 번째 부분식은 주소 중 도메인 주소 부분을 캡처합니다. 이 부분식은 '^', '/' 또는 ':' 문자를 포함하지 않는 문자 시퀀스를 찾습니다. 괄호로 묶은 세 번째 부분식은 웹 사이트 포트 번호가 지정되어 있으면 이를 캡처합니다. 이 부분식은 콜론 다음에 오는 0 이상의 자리 수를 찾습니다. 그리고 마지막으로 괄호로 묶은 네 번째 부분식은 웹 주소로 지정된 경로 및/또는 페이지 정보를 캡처합니다. 이 부분식은 '#' 또는 공백 문자를 제외한 하나 이상의 문자를 찾습니다.
정규식을 위의 URI에 적용하면 부분 검색 문자열에 다음이 포함됩니다.
RegExp.$1은 "http"를 포함합니다.
RegExp.$2는 "msdn.microsoft.com"을 포함합니다.
RegExp.$3은 ":80"을 포함합니다.
RegExp.$4는 "/scripting/default.htm"을 포함합니다.
'프로그래밍언어 > VB.NET' 카테고리의 다른 글
새폼 만들기 (0) | 2013.01.31 |
---|---|
G메일보내기 (0) | 2013.01.29 |
textbox (0) | 2013.01.24 |
문자열 변수 vb.net 기초 (0) | 2013.01.24 |
16↔32컬러만 바로 변경 (0) | 2013.01.24 |