개발자가 편해지는 정규표현식(Regular Expression) 1 - C#

출처: http://ensimple.net/enSimple/show.aspx?cnum=120&b_id=study_csharp&page=1


정규표현식 Syntax 배우기

개발자가 알아두면 손발이 편해지는 정규식 함 알아봅니다.
예전에 유닉스를 하던 때에는 빠삭하게 안다고 자부했었는데, 이게 하나씩 까먹더니 이제는 참조문서를 안보면 작업이 안됩니다.
잘 외워지는 규칙들이 아니라.. 할때마다 참조하려니 귀찮기도 하고, 글로 기록을 해 두려고 합니다.

아래의 글은 http://www.radsoftware.com.au/articles/regexlearnsyntax.aspx 원문을 번역하고 약간 정리한 것입니다.
구글링하다가 우연히 찾은 건데, 심도있는 내용은 아니지만 꼭 필요한 것들을 설명하고 있는 것 같아서 내용을 올려 봅니다.

정규표현식은 현대의 프로그래밍 언어의 한 분야인 패턴 매칭 언어입니다.
정규표현식은 매우 강력한 언어이며, 입력문자열에 패턴을 적용할 수 있게 하고 일치하는 항목들을 결과로 리턴해 줍니다.
정규표현식은 또한 Replacement 패턴을 이용해서 텍스트가 대체되도록 해 주비니다. 이것은 매우 강력한 버전의 찾기/바꾸기(Find/Replace) 수단입니다.

정규표현식을 배우기 위해서 두가지를 알아야 합니다.

- 정규식 구문(Syntax)
- 프로그래밍 언어 내에서 정규식을 이용하는 방법
이번 글은 정규식 구문(Syntax)에 대한 것만 담고 있습니다. 이는 정규식 고유의 구문이라 할 수 있으므로 C# 이 아닌 다른 언어를 사용하더라도 비슷하게 사용할 수 있습니다.
(유닉스 쉘 프로그래밍에서 사용하던 정규식 또한 지금 제가 c# 내에서 사용하는 정규식 구문과 대동소이합니다…. 그럴껍니다… 그렇습니다. (__!))

.NET Framework은 정규표현식을 이용할 수 있는 일련의 클래스들을 System.Text.RegularExpression 네임스페이스로 제공합니다.

일단 들어가기 전에 내가 만든 정규식 구문이 과연 제대로 작성한 것인지 확인하고자 할 경우, 가장 많이 사용하는 방법이 Debugging 입니다. ㅋㅋ Breakpoint 잡아서 이게 제대로 값이 바뀌나 확인하고는 합니다. 참… 원시적(?) 입니다. 저도 그래왔는데, 물론 다른 툴을 설치해서 검증하고자 했지만, 툴 사용법을 잘 이해하지 못했고, 조금 어려운 거 같고 해서.. 즉 귀찮아서 그냥 디버깅으로 했답니다.

원문에서 소개하고 있는 이 툴에 다시 도전해 보려고 합니다. 일단 설치 후 UI는 이해가 쉬운거 같아 마음에 듭니다.
Free Regular Expression Tool
이 툴을 이용해서 아래에 나오는 예제들을 테스트해 보면 될 것이다.

*아래에서 사용하는 용어 "일치시키다"는 matching의 의미입니다. 한글 사용이 더 헷갈리는 것 같습니다.

기본 - 텍스트 찾기

정규표현식은 보통의 문자들 찾아서 일치하는 항목들을 교체하는 것과 유사하다. 만일 "went"라는 단어를 매칭시키고 싶다면 정규표현식 패턴 역시 "went"가 된다.
가령
"Park duck chang is best friend" 라는 입력 문자열에서 "duck"이라는 단어를 찾고싶다면, 정규표현식 패턴 "duck"을 지정하여 일치항목으로서 "duck"을 얻을 수 있다.

정규식에 사용되는 특수한 문자들이 있다.

 . $ ^ { [ ( | ) * + ? \ 

아래에 내용을 통해 이들 각각에 대해서 이해할 수 있다.

Dot(.) : 어떤 문자와도 매칭

점(.)은 개행문자(\n)를 제외한 어떤 문자(공백문자도 포함된다.)와도 일치하는 와일드카드 이다.
예를 들면, 어떤 두 문자 이후에 나오는 'a' 문자가 나오는 패턴을 찾고 싶다면,

Input : abc def ant cow
정규식 : a.. : a문자 다음에 어떤문자 2개가 나오는 패턴
Matches :
abc
ant


만일 Singleline 옵션이 활성화 되었다면, dot(.) 은 개행문자(\n)를 포함한 어떤 문자와도 일치하게 된다. (정규표현식 설정시 사용하는 여러 옵션들이 있다. 예를 들면, 대소문자 구문을 할 건지, 한 라인만 검사 할 건지 등의..이건 나중에 보자..

단어 문자들과 일치시키기

\w 는 어떠한 단어문자와도 일치함을 의미한다.
[a-zA-Z_0-9]과 동일한 의미이다. 즉 알파벳 또는 숫자 또는 언더바(_) 문자 하나와 일치한다. 공백문자나 다른 특수문자등과는 일치하지 않는다.

input: park duck du-- du   chang is best friend.
정규식: du\w\w :'du' 다음에 문자단어가 연속 두개
Matches: duck


위의 예에서 --와 공백 두 개는 일치하지 않는다.

\W 처럼 대문자 W를 사용하게 되면 단어문자가 아닌 한 문자와 일치한다.
위의 예에서 정규식을 du\W\W 바꾸면 결과 matches는 'du--'와 'du  ' 가 된다.

공백 문자와 일치시키기

공백문자는 \s를 이용해 일치시킬수 있다.
(원문에서 \s와 같은 문자를 정규식에서는 character class라고 하는데 이 글에서는 그냥 익숙한 "이스케이프 문자"라는 표현을 쓰도록 하겠다. 딴지 걸지 말기 바란다.)

input: park duck du-- du  chang is best friend. du  chang
정규식: du\s\schang\s :'du' 다음에 공백2개 다음에'chang'다음에 공백1개
Matches: 'du  chang'


위의 예에서 맨 뒤에 오는 du  chang은 일치 결과로 나오지 않는다.

공백문자는 스페이스 문자(스페이스 바)로 정의된다. 개행문자(\n), 폼 피드(\f), 캐리지 리턴(\r), 탭(\t), 수직 탭(\v) 각기 다르다 그래서 위의 예에서 마지막 du  chang 다음문자는 공백문자가 아니라 결과에서 제외되었다.

\s를 사용할 때는 조심해야 하는데 왜냐면, 예기치 않게 개행(\r 과 \n)과 매치될 수도 있으므로 명시적으로 다른 문자를 사용하는게 더 좋다.
궁금해서 테스트 해보니

input : duck du-- du  chang is best friend. du  chang (개행 시킴)

정규식 : du\s\schang\s
Maches :
'du  chang ' : 앞에 것
'du  chang' : 뒤에 것


실제로 테스트 해보니 개행(\r\n)도 일치시키는 것으로 확인되었다.
아래처럼 \r\n으로 테스트하면 결과는 마지막 du  chang만 결과로 보인다.


정규식 : du\s\schang\r\n
Maches :
'du  chang' :뒤에 것


\s를 사용할때는 조금 주의를 기울일 필요가 있을 듯 하다.


숫자와 일치시키기

\d는 0에서 9의 숫자와 일치시킨다.

input: 123 12 843 8472
정규식: \d\d\d
Matches:
123
843
847


단일 문자들의 집합과 일치시키기

[ ] 는 단일 문자들의 집합과 일치시키는데 사용된다. 집합내의 어떤 한 문자와 일치시킨다.

input: abc def ant cow
정규식: [da].. : 'd' 또는 'a'가 오고 다음에 문자 2개
Matches:
abc
def


'^' 문자를 붙이게 되면 그 의미가 반대로 된다. 문자 집합내의 어떠한 한 단어와도일치하지 않는 문자 라는 의미가 된다.

input: abc def ant cow
정규식: [^da].. : 첫문자로 'd'도 아니고 'a'도 아닌 문자가 오고 뒤에 아무 문자(개행문자 제외) 2개
Matches:
"bc "
"ef "
"nt "
"cow"


문자들의 범위에 일치시키기


문자들의 범위는 '-' 문자를 사용해서 일치시킨다.

input: abc pen nda uml
정규식: .[a-d]. : 문자하나 오고 다음문자는 a에서 d 범위 내의 문자 (a or b or c or d)가오고 뒤에 문자하나
Matches:
abc
nda


문자들의 범위는 서로 합쳐질수도 있다.

input: abc no 0aa i8i
정규식: [a-z0-9]\w\w : (a에서 z 내의 문자) 또는 (0에서 9 내의 문자) 하나가 오고 뒤에 단어문자2개
Matches:
abc
0aa
i8i


[] 안에서 특별하게 지시하지 않아도 명시된 문자들 간의 OR 조건을 가정한다.
[abc] : a OR b OR c
[a-b0-4] a-b OR 0-4

위의 예에서 본 것을 좀 더 간단한 패턴으로 표현하면 [a-z\d]이 될수 있다.
a-z OR \d(숫자)

반복(수)지정자(Quantifiers)를 이용해서 일치하는 회수를 명시하기

가장 자주 사용되는 반복지정자는 *, +이다.

* : 0번 이상의 반복과 일치시키기

*는 문자, 그룹, 또는 이스케이프 문자가 optional 하다는 의미이다. 즉 지정한 문자가 나와도 되고 안나와도 상관없단 뜻이다.

input: Anna Jones and a friend owned an anaconda
정규식: a\w* : a 문자나오고 뒤에 단어문자([a-zA-Z_0-9])가 0개 이상 오는 패턴
Options: IgnoreCase : 대소문자 무시 옵션
Anna
and
a
an
anaconda


+ : 한번 이상의 반복과 일치시키기

*는 문자, 그룹, 또는 이스케이프 문자가 반드시 한번은 나와야 한다는 것을 의미한다.

input: Anna Jones and a friend owned an anaconda
정규식: a\w+ : a 문자 뒤에 단어문자가 하나이상 오는 패턴
Options: IgnoreCase
Matches:
Anna
and
an
anaconda


사실 여기서 의문이 든다. anaconda 같은 경우에 일치하는 패턴이 두번 나온다.
Anaconda 전체가 하나이고 또 내부에도 있다. Aconda
근데 일치항목에는 Anaconda만 나온다. 왜그럴까.. 일치항목으로 결정된 텍스트 내에서는 다시금 패턴 검사를 하지 않는다 라는 룰이 있나?...추측일 뿐이다. 답을 아시는 분은 답변 좀 달아주시라.


? : 0번 또는 1번의 반복과 일치시키기

물음표는 0번 또는 1번만 나오는 패턴을 의미한다.

input: Anna Jones and a friend owned an anaconda
정규식: an? :a문자 뒤에 n문자가 0번 또는 1번 나오는 패턴
Options: IgnoreCase
Matches: Anna Jones and a friend owned an anaconda
An
a
an
a
an
an
a
a


맨 앞 텍스트 Anna 에서 An만 일치 결과로 나온다는 것을 잘 봐야 한다. 사실 Anna 이면 a 나오고 n이 두번 나오니까 이건 패턴 매칭 안될거야. 라고 판단했지만, 다르게 생각해보니,
Anna 라는 단어를 생각하면 패턴 매칭이 아니다. 그러나 그 안의 문자들 하나하나를 따졌을 때 an까지 패터매칭이고 ann은 아니고 anna도 아니다. 다 해보자 nna도 아니고, na도 아니고, a도 아니다. 그래서 결과로서 an만 나온것이다. 음.. 정규표현식이 이렇게 판단하는 거구나 짐작을 할 수 있다.


패턴 일치의 반복수를 명시하기

{n} 형식으로 한 문자, 그룹, 이스케이프 문자를 위해 요구되어지는 일치의 최소 반복수를 명시할 수 있다.

input: Anna Jones and Annnnne owned an anaconda
정규식: an{2} : a문자 다음 n문자가 최소2번 나오는 패턴
Options: IgnoreCase
Matches:
Ann
Ann


{n, m} 식으로 명시할 수도 있는데 여기서 n은 일치의 최소 반복수 m은 일치의 최대 반복수를 의미한다.

input: Anna and Anne lunched with an anaconda annnnnex
정규식: an{2,3} : a문자 나오고 다음 n문자는 2번 이상 3번 이하로 나오는 패턴
Options: IgnoreCase
Matches:
Ann
Ann
annn


annnnnex 단어도 결과에서 빠질 줄 알았겠지만, 이 단어 내에서 annn 만 뜯어서 보변 패턴 매칭이다. 그래서 결과로 annn 이고 이 결과 내에 또 패턴 매칭이 있지만 annn에서 ann이 패턴 매칭이지만 위에서 나름대로 유추한 정규표현식의 룰 "결과항목 내에서 패턴 검색을 다시 하지 않는다" 라는 룰을 적용하면 annn 만이 결과항목으로 나오게 된다.
(만약 이 룰이 아니라면..-_-!!! .. 아는분 답변 좀 부탁한다..)


문자열의 시작과 끝 일치(match) 시키기

문자열의 시작에서 나타나야 하는 패턴은 '^' 문자를 사용합니다.

input: an anaconda ate Anna Jones
정규식: ^a : 문자열의 시작에 나오는 a문자
Matches:
"a" : 맨 처음 나오는 a 문자임


'^' 문자는 [] 안에서 사용될 때와 밖에서 사용될 때 그 의미가 다르므로 주의해야 한다.

만일 Multiline 옵션이 켜져 있다면, ^ 는 각 라인의 시작과 일치(match)하게 된다.
위의 문자열 시작과 같은 의미로 문자열의 종료는 '$'를 사용한다. 역시 Multiline 옵션이 켜져 있으면 각 라인의 마지막과 일치(match) 하게 된다.

input: an anaconda
ate Anna
Jones
정규식: \w+$ : 단어문자([a-zA-Z_0-9])가 1번 이상 나오고 문자열이 종료되는 패턴
Options: Multiline, IgnoreCase
Matches:
Jones
tags :
나의일/.NET 2007/08/10 19:30

트랙백 주소 : http://www.ddosori.net/trackback/6

댓글을 달아 주세요

  1. 김시억 2009/04/27 01:23  수정/삭제  댓글쓰기

    질문좀 드리겠습니다
    post 로 값을 던졌습니다.....그리고...

    HttpWebRequest를 이용하여 얻어진 쿠키값을 이용하여 WebBrowser를 사용하고 싶습니다.

    HttpWebRequest HTTP = (HttpWebRequest)WebRequest.Create("a-login URL");
    HTTP.CookieContainer = new CookieContainer();
    HTTP.Method = "POST";
    HTTP.ContentType = "application/x-www-form-urlencoded";
    MemoryStream bufferStream = new MemoryStream();
    byte[] LoginParamattaBytes = System.Text.Encoding.GetEncoding("EUC-KR").GetBytes("ID=aa&PW=bb");

    bufferStream.Write(LoginParamattaBytes, 0, LoginParamattaBytes.Length);
    HTTP.ContentLength = bufferStream.Length;
    bufferStream.WriteTo(HTTP.GetRequestStream());
    bufferStream.Close();

    LoginCookie = HTTP.CookieContainer; <== 로그인후 쿠키값 LoginCookie

    위 HttpWebRequest를 이용하여 얻어진 쿠키값을 이용하여 webBrowser1에 접속하고싶습니다.
    webBrowser1.Navigate("로그인 쿠키값이 필요한 URL");<-이렇게 제응용플에서 저쿠키를
    가져와 로그인유지하며 다른페이지로 가려고 합니다....
    방법좀 알려주시면 대단히 감사하겠습니다

    webBrowser1.Navigate(a-다른페이지, null, null, webBrowser1.Document.Cookie);
    이런식으로는 적용이 안되더라고요;;;;

    제이메일주소는 automute@live.co.kr입니다 곽창수입니다

  2. 돌비 2009/07/03 16:34  수정/삭제  댓글쓰기

    좋은 정보 잘 보고 갑니다.
    감사합니다~~~

Powerd by Tistory, designed by criuce
rss