정규식(Regular expressions, Regex 또는 Regexp)은 특정 검색 패턴(ASCII 또는 유니코드 문자의 시퀀스)에 대한 하나 이상의 일치 항목을 검색하여 텍스트에서 정보를 추출하는데 매우 유용합니다.
가장 흥미로운것 중 하나는 정규식을 학습한 후에는 거의 모든 프로그래밍 언어(Javascript, Java, VB, C#, C, C++, Python, Perl, Ruby, Delphi, R, Tcl 등등)에서 동일하게 사용할 수 있다는 것입니다. 엔진이 지원하는 문법버전 이나 최신특징에 따라서 약간의 차이만 있을 뿐입니다.
자, 이제 몇가지 예제와 설명을 통해 시작하겠습니다!
Basic topics
Anchors — ^ and $
^The The 로 시작하는 모든 문자열을 매칭합니다 -> 실습해보세요!end$ end로 끝나는 문자열과 매칭합니다^The end$ The end와 정확하게 일치하는 문자열을 매칭합니다roar roar가 들어있는 모든 문자열과 매칭합니다
Quantifiers — *+? and {}
abc* ab 그리고 0개 이상의 c 를 포함한 문자열과 매칭합니다 -> 실습해보세요!abc+ ab 그리고 1개 이상의 c 를 포함한 문자열과 매칭합니다abc? ab 그리고 0개 또는 1개의 c 를 포함한 문자열과 매칭합니다 abc{2} ab 그리고 2개의 c 를 포함한 문자열과 매칭합니다 abc{2,} ab 그리고 2개 이상의 c 를 포함한 문자열과 매칭합니다abc{2,5} ab 그리고 2개 이상 5개 이하의 c 를 포함한 문자열과 매칭합니다a(bc)* a 그리고 0개 이상의 bc를 포함한 문자열과 매칭합니다a(bc){2,5} a 그리고 2개 이상 5개 이하의 bc를 포함한 문자열과 매칭합니다
OR operator — | or []
a(b|c) a 그리고 b 또는 c를 포함한 문자열과 매칭합니다 -> 실습해보세요!a[bc] 위와 동일합니다
Character classes — \d \w \s and .
\d 숫자 하나와 매칭합니다 -> 실습해보세요!\w 문자(숫자, 영문, 언더바) 하나와 매칭합니다 -> 실습해보세요!\s 공백문자(탭, 줄바꿈, 스페이스) 하나와 매칭합니다. 모든 문자 하나와 매칭합니다 -> 실습해보세요!
클래스 또는 부정문자 클래스가 더 빠르고 정확하기 때문에 .
연산자는 조심스럽게 사용하세요.
\d
, \w
, \s
도 각각 \D
, \W
, \S
로 표시하면 반대의 의미로 매칭시킬수 있습니다.
예를 들어, \D
는 \d
의 매칭 값과 반대로 매칭을 수행합니다.
\D 숫자가 아닌 문자열 하나와 매칭합니다 -> 실습해보세요!
특수문자(^.[$()|*+?{\
)를 문자 그대로 사용하려면, 역슬래시\
를 앞에 붙여야합니다.
\$\d $ 문자 그리고 숫자 하나와 매칭합니다 -> 실습해보세요!
출력이 불가능한 탭문자\t
, 줄바꿈문자\n
, 캐리지리턴문자\r
또한 매칭할 수 있습니다.
Flags
우리는 정규식을 만드는 방법을 배우고 있지만, 기본적인 개념인 flags를 배워야 합니다.
정규식은 보통 /abc/
와 같은 형식을 사용하며, 두개의 슬래쉬 문자/
사이에 정규식을 작성합니다. 두번째 슬래쉬 뒤에 플래그를 사용할 수 있습니다.
- g(global) 문자열에서 첫번째 매칭 후, 끝나지 않고 매칭되는 모든 항목을 찾습니다
- m(multi-line) anchor(
^
또는$
)가 문자열 전체가 아닌, 줄 각각에 매칭하여 줄별로 정규식 패턴을 매칭시킬 수 있습니다 - i(insensitive) 대소문자 구분을 무시하고 매칭합니다(예를 들어,
/aBc/i
는AbC
를 매칭합니다)
Intermediate topics
Grouping and capturing — ()
a(bc) 소괄호는 캡쳐 그룹을 생성합니다 -> 실습해보세요!a(?:bc)* ?: 는 캡쳐 그룹생성을 무시합니다 -> 실습해보세요!a(?<foo>bc) ?<foo> 는 캡쳐 그룹에 이름을 지정합니다 -> 실습해보세요!
이 연산자는 문자열로부터 정보를 추출할 때 매우 유용합니다. 여러 그룹으로 캡쳐된 결과는 배열로 반환됩니다. 따라서, index로 캡쳐된 내용을 사용할 수 있습니다.
?<foo>
형태를 사용하여 그룹에 이름을 지정하면 값을 key-value
형태를 가진 dictionary처럼 접근하여 사용할 수 있습니다.
Bracket expressions — []
[abc] a 또는 b 또는 c 를 포함하는 문자열과 매칭합니다
-> a|b|c와 동일합니다 -> 실습해보세요![a-c] 위와 동일합니다[a-fA-F0-9] 16진수의 문자 하나와 매칭하고 대소문자를 구분하지 않습니다 ->실습해보세요![0-9]% 0이상 9이하 숫자 그리고 %문자를 포함한 문자열과 매칭합니다[^a-zA-Z] 영문이 아닌 문자와 매칭합니다 ^는 부정표현으로 사용합니다 ->실습해보세요!
대괄호식에서는 특수문자의 특별한 힘이 동작하지 않기 때문에, 백슬래쉬\
로 escape
시키지 않아도 됩니다.
Greedy and Lazy match
수량표현식 (* + {}
)은 욕심많은 연산자이기 때문에, 제공된 데이터에서 최대한 많이 매칭하려고 합니다.
예를 들어, <.+>
는 This is a <div> simple div</div> test
문장에서 <div>simple div</div>
를 매칭시킵니다. 만약 div
태그만 매칭하려면 뒤에 ?
를 사용하여 Lazy하게 만들 수 있습니다.
<.+?> < 와 > 사이에 하나 이상의 문자와 매칭하고, 가능한 짧게 매칭합니다.
-> 실습해보세요!
더 나은 방법은, .
연산자를 사용하지 않고 좀더 엄격한 정규식을 사용하는 것입니다.
<[^<>]+> < 와 > 사이에 <,>가 아닌 모든 문자가 하나 이상인 문자와 매칭합니다
-> 실습해보세요!
Advanced topics
Boundaries — \b and \B
\babc\b abc와 동일한 문자를 매칭합니다 -> 실습해보세요!
\b
는 anchor 문자(^ 또는 $)와 유사하며 한쪽은 문자를 의미하며, 다른 쪽은 문자가 아닌 단어와 매칭합니다
\B
는 \b
와 매치되지 않는 문자열과 매칭합니다. 단어로 쌓여있는 패턴을 찾을 때 사용합니다.
\Babc\B 패턴이 단어로 완전히 둘러싸인 경우 매칭합니다 -> 실습해보세요!
Back-references — \1
([abc])\1 \1은 첫번째 캡쳐그룹과 동일한 패턴을 의미합니다 -> 실습해보세요([abc])([de])\2\1 \2는 두번째 캡쳐그룹과 동일한 패턴을 의미합니다
([abc])([de])([de])([abc])와 동일합니다
(\3, 4 ... 매칭된 그룹을 의미합니다) -> 실습해보세요!(?<foo>[abc])\k<foo> \k<foo>는 foo이름으로 지정한 그룹을 참조합니다
결과는 첫번째와 동일합니다 -> 실습해보세요!
Look-ahead and Look-behind — (?=) and (?<=)
d(?=r) r이 바로 뒤에 있는 d를 매칭합니다. 중요한 것은 r은 포함되지 않습니다.
-> 실습해보세요!(?<=r)d r이 바로 앞에 있는 d를 매칭합니다. 중요한 것은 r은 포함되지 않습니다.
-> 실습해보세요!
또 다른 부정연산자 입니다!
d(?!r) r이 바로 뒤에 없는 d를 매칭합니다. 중요한 것은 r은 포함되지 않습니다.
-> 실습해보세요!(?<!r)d r이 바로 앞에 없는 d를 매칭합니다. 중요한 것은 r은 포함되지 않습니다.
-> 실습해보세요!
요약
지금까지 보았듯, 정규식은 응용을 통하여 여러상황에서 사용할 수 있습니다. 개발자라면 충분히 숙지하고 있어야 합니다. 아래는 그 예입니다.
- 데이터 유효성 검사 (휴대폰, 이메일, 시간문자열 등등)
- 데이터 스크래핑 (특히, 웹 스크랩핑작업은 특정 패턴으로 정보를 스크랩하는 것이 중요합니다)
- 문자열 파싱 (URL 쿼리파라미터 파싱, 괄호 파싱 등등)
- 문자열 대체 (;를 ,로 변경, 대소문자 변경 등등)
- 문법 highlighting, 파일명 변경, 패킷 스니핑 등등 문자열을 다루는 여러 응용로직에서 사용가능합니다.