정규표현식의 개념과 기초 문법

작성한지 10년이 지났는데도 notepad++ 관련한 키워드로 꾸준히 유입이 발생하고 있고,  그게 정규 표현식 관련한 글인데 별로 내용이 좋은 글이 아니다. (몇 가지 기초적인 문법만 요리책 식으로 나열해 놓은 거라…) 그래서 정규 표현식의 개념과 기초 문법 그리고 몇 가지 이 블로그에서 다루는 언어들에서 정규 표현식을 어떻게 쓰는지, 어떤 것들을 할 수 있는지 등에 대해서 알아볼 계획이다.

오늘은 그 첫 번째 순서로, 정규 표현식의 개념과 가장 기초가 되는 패턴 문법에 대해서 살펴보려고 한다.

정규 표현식의 개념

정규표현식은 줄여서 정규식(영어로는 Regular Expression이고 줄여서 Regex, Regexp 등으로 불린다.) 이라고도 하는데, 컴퓨터 과학의 정규언어로부터 유래한 것으로 특정한 규칙을 가진 문자열의 집합을 표현하기 위해 쓰이는 형식언어이다.

일반적인 어휘를 써서 풀어보자면 어떤 텍스트 내에서 특정한 형태나 규칙을 가진 문자열을 찾기 위해 그 형태나 규칙을 나타내는 패턴을 정의하는 것이 정규 표현식이라고 이해하면 된다.

정규 표현식의 종류

정규 표현식은 다양한 분야에서 쓰이기 시작했는데 각 분야의 정규식은 서로 영향을 주고 받으면서 발전해서 지금에 이르렀다. 아니 왜 아름다운 역사 이야기를 갑자기 들먹이는 거냐면, 바로 정규식이 이렇게 쓰이는 곳이 다양한데, 하나의 통일된 표준이 아니라는 것이다.

유닉스 명령줄 도구들에서 사용하던 정규 표현식은 POSIX 표준에 편입되었다. 그리고 이후에 다시 POSIX 정규식은 POSIX BRE (POSIX 기본 정규식)와  POSIX ERE (POSIX 확장 정규식)으로 다른 버전이 나뉘게 된다. (grep에서 -e 스위치를 써서 확장 정규식을 쓰던 옵션이 바로 ERE를 쓴다는 의미이다.) 그외에 BRE를 기본 골격으로 한 vim 정규식이 있다. 역시 오랜 역사를 따라 개선과 확장을 거듭하면서 이는 POSIX 표준과는 좀 다른 규격으로 취급될 정도이다. 1:

그리고 문자열을 다루는데 특화된 스크립트 언어인 펄(perl)이 등장했다. 펄의 정규식 체계는 역시나 기본은 POSIX와 비슷한데, 엄청나게 많은 확장이 들어갔다. 이후 펄의 정규식은 PCRE라는 규격으로 정리되었으며, 이후 많은 프로그래밍 언어들이 이 규격을 차용하거나, 계승한다. 여기서 중요한 것은 “일부 차용”이다. 이 규격은 워낙 방대해서 PCRE를 그대로 가져다 쓰지 않는 이상, 구현할게 너무 많기 때문이다.

참고로 Cocoa에서는 ICU 표준의 정규식을 따른다. 이 라이브러리 역시 PCRE를 기반으로 하고 있으며, 유니코드 문자열에 대한 정규식 패턴 매칭을 수행하는 알고리듬이 구현되어 있다.

정규식 기본 문법

정규식 기분 문법은 크게 세 가지 정도로 나눌 수 있다.

  1. 패턴 그대로를 매칭하는 경우 : 편집기에서 “찾기” 기능을 통해서 특정 단어를 찾는 것 처럼, 단어 그대로를 패턴으로 사용하여 매치되는 영역을 찾는다.
  2. 메타문자 및 수량 한정자를 적용하는 경우 : 정규식 패턴에 쓰이는 문자중에는 특별한 의미를 가지는 메타 문자들이 있는데, 이들을 사용하여 보다 폭넓은 패턴에 매치할 수 있다.
  3. 그룹 및 look around 기능을 사용하는 경우 : 제법 고급 정규식이라 할 수 있는 부분으로, 패턴의 일부를 그룹으로 묶거나, 특정 패턴의 앞 뒤로 다른 패턴이 오는 조건을 더하는 경우이다.

정규식 메타 문자

메타 문자는 특정한 문자 혹은 문자 계열을 대신하여 표시하는 문자이다. 메타문자를 이용하면 특정한 규칙을 가진 여러 단어를 하나의 패턴으로 함축할 수 있다.

정규표현식의 개념과 기초 문법 더보기

vim의 정규식 기호와 very magic 모드

vim의 문자열 검색, 치환 기능은 패턴 매칭에 의한 것이며, 이 패턴 매칭은 정규식에 기반을 두고 있다. 그런데 정규식 문법을 조금 알고 있는 상태에서 vim의 정규식을 사용하면 깊은 빡침을 느끼거나 심한 멀미를 겪을 수 있다. 왜냐하면 정규식은 딱히 하나의 정해진 표준도 없거니와 기능과 편의를 위해서 여러 갈래로 나뉘어져 있고 vim에서는 상황에 따라서 서로 다른 기준을 사용해서 패턴을 파싱하기 때문이다. 예를 하나 들어보자.

(this)isnot{this}nor[this]

이런 문자열이 있다고 할 때, 괄호들을 포함한 this를 검색, 즉 (this), {this}, [this]를 검색하려면 다음의 패턴을 사용한다. vim의 정규식 기호와 very magic 모드 더보기

[Python | Javascript] URI로부터 파일이름 구하기

자바스크립트와 파이썬 버전의 함수.

function getFilename(url)
{
	var pattern = /(^.*\/)([^&#?]*)/;
	var m = url.match(pattern);
	var filename = m[2];
	return filename;
}

 

import re

def getFilenameFromURL(url):
    pattern = "(^.*/)([^&#?]*)"
    c = re.compile(pattern)
    r = c.findall(url)
    return r[1]

 

 

[Javascript] 현재 페이지의 URL에서 도메인 주소 구하기

현재 페이지의 URL로부터 도메인 주소만 구하는 방법

도메인 주소는 알파벳문자와 숫자, 구두점(.), 하이픈(-)으로 이루어진다. 따라서 다음 코드로 구할 수 있다.

document.location.href.match(/http[s]*:\/\/([a-zA-Z0-9\-\.]*)/)[1]

20071111 : notepad++ 과 정규표현식

[update] : 정규식 관련하여 근 10년만에 기초적인 내용을 이 글보다 조금 더 체계적으로 정리한 포스트를 발행하였으니, 아래 글 보다는 새 글을 먼저 읽어 보실 것을 권합니다. 20071111 : notepad++ 과 정규표현식 더보기