Brise

정규 표현식(Regular expression) 쉽게 이해하기 본문

프로그램

정규 표현식(Regular expression) 쉽게 이해하기

naudhizb 2017. 6. 16. 00:18
반응형

정규 표현식이란?


정규 표현식은 특정한 문자열의 규칙을 표현하는데 사용하는 형식언어이다.

(즉, 특정 규칙을 가지고 있는 문자열들; e.g. 1글자의 알파벳 소문자 = a,b,c,d,...)


보통 '문자열의 규칙'을 표현하기 위해서는 일반적인 조건문을 이용하면 복잡하게 표현해야하지만, 

정규표현식을 이용하면 간결한 형태로 표현할 수 있다. 


하지만, 규칙에 대하여 잘 숙지하지 않으면(규칙을 이해하고 있더라도 찬찬히 뜯어보기 전에는..) 

알아보기 힘든 형태를 띄고 있는 것 또한 사실이다. 


정규 표현식은 크게 문자와 메타문자로 구성된다.

아래에서 먼저 메타문자에 대하여 설명 한 뒤 메타문자와 문자를 이용하여 어떻게 정규표현식을 사용하는지 알아보도록 하자. 


메타문자


메타문자는 문자를 표현하는 것 이외에 특정한 규칙을 표현하기 위한 문자들이다.

대부분의 경우 같은 메타문자들을 사용하지만 특정 종류에 따라 메타문자가 다른 경우도 있으므로 

제대로 사용이 안될 경우 해당 정규식의 표현 방법을 찾아보아야 한다. 


^x     : 입력(줄) 시작 + x

x$     :  x + 입력(줄) 끝

\Ax    : 문자열의 시작(내부 줄바꿈 제외) + x

x\z    : x + 문자열의 끝(내부 줄바꿈 제외)


.      : 개행 문자를 제외한 임의의 문자 1개

x{n}   : x가 n번 반복

x{n,}  : x가 n번 이상 반복

x{n,m} : x가 n번 이상 m번 이하 반복

x?     : 문자 x 또는 문자 없음(x{0,1})

x+     :  x가 1번 이상 반복(x{1,})

x*     : x 가 0번 이상 반복(x{0,})


--> +, *, {n,m}과 같이 여러 값을 가질 수 있는 규칙의 경우 기본적으로 greedy(좀 더 큰 결과값을 찾음)하게 동작하지만 ?기호를 붙이면 lazy(작은 결과를 찾음)하도록 동작한다. 


x|y    : x 또는 y

(x)    : ()안의 내용을 캡쳐하여 그룹화 (레퍼런스 캡쳐 관련하여 Ref.2를 참조바람)

(x)(y) : ()안의 내용을 캡처하며 앞에서부터 그룹 번호를 부여함.

(?:y)  : 캡쳐하지 않는 그룹을 생성

\n     : (n은 1에서 9까지의 정수 [1-9])정규식 안 n번 괄호(그룹)의 최근 일치 부분(역참조)과 같음.

x(?=y) : y가 뒤 따라오는 x에만 일치

x(?!y) : y가 뒤 따라오지 않는 x에만 일치

[...]  : Bracket expression이며 가능한 문자셋을 표시한다.(자세한 내용에 대해서는 후술)


정규 표현식에서 이스케이프 문자 '\' 뒤에 사용되는 문자를 특별하게 해석할 것을 요구하며, 

특수한 문자(또는 문자집합)나 메타문자에서 먼저 사용하고 있는 글자(e.g. [](){}^$ 등)를 표시하기 위하여 사용한다. 



\A     : 문자열의 시작(내부 줄바꿈 제외)

\z     : 문자열의 끝(내부 줄바꿈 제외)

\w     : '_'를 포함한 알파벳 또는 숫자 [A-Za-z0-9_]

\W     : 비 단어문자 [^A-Za-z0-9_]

\b     : 길이가 0인 단어의 경계를 의미 즉, 매칭되는 결과물에는 경계가 포함되지 않는다(^\w | \w$ | \W\w | \w\W) (Ref.3)

\B     : 단어의 경계가 아닌 것.

\d     : 숫자 문자 [0-9]

\D     : 숫자 문자가 아닌 것 [^0-9]

\xhh   : hh(hex문자 2개)

\uhhhh : hhhh(hex문자 4개)

\f     : 폼 피드(U+000C)

\n     : 줄 바꿈(U+000A)

\r     : 캐리지 리턴(U+000D)

\t     : 탭(U+0009)

\v     : 수직 탭(U+000B)

\s     : 스페이스, 탭, 폼 피드, 줄 바꿈 문자를 포함한 하나의 공백문자 [ \f\n\r\t\v​\u00a0\u1680​\u180e\u2000​-\u200a​\u2028\u2029\u202f\u205f​\u3000]

\S     : \s가 아닌 모든 문자

\0     : 널 문자(U+0000)

\c     : 컨트롤 문자(e.g. \cM 은 control-M(U+000D)와 일치함)



[](Bracket expression)


[]을 통하여 문자셋을 표현할 때에 주의할 점은 대괄호 안에서는 메타문자를 사용할 수 없거나 

일반 문자가 다른 형태로 사용되게 된다. 


[a-z]  : a부터 z까지의 문자

[^ab]  : a와 b를 제외한 모든 문자(^는 '줄의 시작'으로 처리되지 않고 not으로 처리된다.)

[ac]   : a | c

[a.c]  : a | . | c ('.'이 임의의 문자로 처리되지 않고, 문자 '.'로 처리된다.)

[\b]   : 백스페이스

[-]    : '-' 문자의 경우 문자로 인식되기 위해서는 []안에 첫 번째 혹은 마지막으로 위치하여야 한다. 

[]]    : '[' 문자의 경우 문자로 인식되기 위해서는 []안에 첫 번째 혹은 ^문자 바로 다음에 위치하여야 한다.



캐릭터 클래스(POSIX Extended)


[...]를 이용하여 문자셋을 표현하는 것이 가능하지만, 직관적으로 이해하기 힘든 점이 있을 수 있다.

때문에 직관적으로 이해하기 쉬운 형태로 문자셋을 표현할 수 있도록 캐릭터 클래스를 제공하고 있으며 그 내용은 다음과 같다.

(표준이 아닌 부분이 있을 수 있음)


[:alnum:] : 알파벳 및 숫자 [A-Za-z0-9]

[:alpha:] : 알파벳 [A-Za-z]

[:blank:] : 공백과 탭[ \t]

[:cntrl:] : 컨트롤 문자 [\x00-\x1F\x7f]




플래그 


플래그를 이용하여 정규식의 검색 방법을 설정할 수 있다. 


g : 전체 검색

i : 대소문자 무시

m : 여러 줄 검색

y : 현재 위치부터 검색



예제


정규표현식을 이용하여 특정 규칙이 있는 여러 문자열들을 검색할 수 있다. 


e.g. 핸드폰 번호 찾기


홍길동 : 010-1234-5678

에서 핸드폰 번호를 찾고 싶다면

\d{3}-\d{4}-\d{4} 과 같이 값을 찾을 수 있다. 


만약 이 중에서 끝 4자리가 5천이 넘는 숫자를 찾고 싶다면

\d{3}-\d{4}-[5-9]\d{3} 와 같이 찾을 수 있다. 


속칭 '황금번호'와 같은 패턴을 찾고 싶다고 한다면 그룹의 역참조를 이용하여 찾아야 한다. 

( 괄호('()')를 이용하여 그룹을 캡쳐하고 캡처한 내용을 \1~\9를 이용하여 역참조 한 형태로 반복시킨다.)

010-AAAA-BBBB 와 같은 형태라면

/010-(\d)\1{3}-(\d)\2{3}/ 와 같이 찾을 수 있을 것이다. 



e.g. 파일 이름 찾아보기


자주 컴퓨터에서 파일을 찾는 사람들의 경우 윈도우의 검색이 느리기 때문에 'Everything'이라는 프로그램을 종종 사용하는 경우가 있다. 


이 프로그램에서는 정규표현식을 이용한 찾기를 지원하는데(사실 Ctrl+f로 호출할 수 있는 대부분의 찾기가 정규표현식을 제공한다.)


정규표현식을 사용하지 못하는 경우 파일을 찾는데 애를 먹는 경우가 있다. 



예를 들어 c:\ 안에 있는 모든 hello.c 파일과 hello.h 파일을 찾고싶다면


c:\\.+\\hello\.[ch]$ 라고 찾을 수 있을 것이다. 


찬찬히 뜯어보면


c:\\ : c:\를 뜻하며 \가 메타문자로 해석하길 요구하는 글자이기 때문에 \\로 사용한다. 

.+ : 1개 이상의 문자를 뜻한다. 따로 요구하지 않는 경우 정규표현식 검색은 greed(더 큰 것을 찾는다)하게 동작하기 때문에 최대한 많은 길이를 찾는다. 

hello\. : hello. 을 뜻함.

[ch]$ : c 또는 h를 의미하며 $가 붙었기 때문에 이 줄의 끝일 경우에만 매칭된다. 


와 같이 해석 가능하다. 



e.g. 특수한 문자열 찾기


정규표현식을 익히는 좋은 방법중의 하나는 아주 긴 문자열들을 다뤄보는 것이다. 


Python challenge 의 문제에 이런 문제가 있었는데, (물론 기억에 의존하는 것이기 때문에 정확히 같은 문제는 아니다.)

" 3개 이상의 큰 알파벳 사이에 같힌 글자를 찾아라" 였다.

그리고 문자열을 보면 알파벳 뿐만 아니라 온갖 기호들이 섞여있다. 


여기서 매칭되는 문자를 찾기 위해서는 조건문을 꽤나 복잡하게 만들어야 하는데

정규표현식을 이용하면 간단하게 찾아낼 수 있다. 


[A-Z]{3,} : 3개 이상의 큰 알파벳

[a-z] : 작은 알파벳

[A-Z]{3,} : 3개 이상의 큰 알파벳


이렇게 찾고 ()괄호를 이용해서 작은 알파벳을 캡쳐하면


[A-Z]{3,}([a-z])[A-Z]{3,}


와 같이 정규표현식이 나오고 결과값은 그룹으로 지정되어 리스트형태로 도출된다. 





이런 방식으로 다양하게 정규 표현식을 사용 가능하니


필요할 때 보고 편리하게 사용해 보도록 하자. 





Reference :


[1] https://en.wikipedia.org/wiki/Regular_expression

[2] http://www.regular-expressions.info/refcapture.html

[3] http://www.regular-expressions.info/wordboundaries.html

[4] http://www.nextree.co.kr/p4327/

반응형
Comments