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

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

 

C# Regular Expression(Regex) Examples in .NET

오늘은 http://www.radsoftware.com.au/articles/regexsyntaxadvanced.aspx 의 내용을 소개한다. 내가 이 사이트의 글을 소개하는 건 이 사이트 소유사와 친분이 있는 것도 아니고, 글쓴이와 친한것도 아니다. 외국 사이트고 외국인이다. 나랑 안 친하다.
그러나 글이 간결하고 이해하기 쉬운거 같아서 소개하고자 한다. 이런식의 번역이나 소개가 "저작권 법에 위배되는" 짓이라면 나를 쳐라! 기꺼이 맞아주겠따 *_*. (단 지적재산권 침해에 의한 벌금" 머 이런식으로 나오면 바로 잠수하겠다. 돈없다.) 이전에 올린 CodeGuru의 글에 대해서는 이들이 나의 뜻을 가상히 여겨 아무런 응대가 없따. 나의 진심이 통했다고 본다…


인터넷을 통해 많은 것을 배우고 많은 기술과 팁을 얻는다. "야.. 인터넷이 없다면 내가 일을 제대로 할 수 있을까?..." 라는 생각을 많이 하여왔다.
나는 생각한다. "베이스가 갖추어진 개발자가 가질수 있는 최고의 무기는 "검색"의 기술이다." "검색"의 기술은 발생한 문제로부터 핵심적인 키워드를 찾아내는 것이 가장 중요하다고 본다.
일단 우리는 어떤 문제에 봉착하게 되면 가장 먼저 도움말을 찾게된다. 그러나 도움말이 인도하는 정도의 길 만으로는 도저히 해결이 날 것 같지 않은 문제들(대부분 버그)은 나 이외에 다른 사람이 겪은 동일한 경험이 최고의 답이 될 수 있다. 직관적이고 빠르고, 이해하기 쉽게 나의 문제를 이야기하기 때문에 빨리, 효율적으로 문제를 해결할 수 있다. 그리고 그 경험자들이 있는 곳이 바로 인터넷이다.
(물론 발생하는 대부분의 문제는 기본과 개념을 숙지한 개발자들이 스스로 해결이 가능하다고 믿는다. )



특수문자를 이스케이프 문자와 일치시키기

탭과 캐리지 리턴과 같은 특수문자는 이스케이프 문자와 일치시킬수 있다.

\t : 탭과 일치
\r : 캐리지 리턴과 일치
\n : 개행(new line)과 일치
\u0020 : 16진수 표현을 사용하는 유니코드 문자와 일치, 정확하게 4개 숫자로 명시

Input: an anaconda ate
Anna Jones
정규식: \w+\r\n : 단어문자([a-zA-Z_0-9]) 하나 이상 나오고, 뒤에 캐리지 리턴 나오고 개행 나오는 패턴, 일반적으로 캐리지리턴(\r)과 개행(\n)이 합쳐져서 "엔터 키"가 된다.
Match:
ate


OS에 따라서 \r과 \n 문자가 합쳐져야만 새로운 개행을 의미하기도 한다. 윈도우 시스템의 경우 일반적으로 \r\n를 사용해야만 새로운 개행을 의미하게 된다. 간단히 라인의 끝(end of line) 또는 문자열의 끝과 일치시킬때는 $를 사용한다.

그룹핑과 일치시키기
그룹은 조금 다른 기능을 수행한다. 그룹은 반복(수)지정자(Quantifiers) : +, *, ? 가 개별적인 문자 대신에 섹션별로 적용되어지게 한다.
하나의 그룹은 ()에 의해서 명시된다. 그러나 입력 문자열에서 ()와 같은 괄호 문자와 매치시키고 싶다면 이스케이프 문자를 사용해야 한다. \(, \) 왜냐면 ()는 정규식에서 그룹을 위한 예약 문자이므로, 다른 예약문자들도 다 똑 같은 내용이 적용된다.


input: http://www.yahoo.com/index.html and http://yahoo.com
정규식: http://(www\.)?([^\.]+)\.com
Matches:
http://www.yahoo.com
http://yahoo.com

위의 예를 보자.
http://(www\.)?([^\.]+)\.com 라는 패턴이 의미하는 바는, http:// 라는 문자들이 오고 뒤에 (www\.) 라는 섹션(=그룹, 즉 www. 문자열, 여기서 . 역시 예약문자이므로 이스케이프 해서 매치시키고 있다.)이 반복지정자 ? 이므로 0번 또는 1번 나오게 되고, ([^\.]+) 라는 섹션(=그룹, 즉 "."가 아닌 문자가 1번 이상 나오게 되는 문자열)이 나오게 되고, 그 뒤에 ".com" 이 나오는 패턴이다.

이 패턴에서 특히 (www\.)? 가 그룹의 용도를 설명해 준다. 특정 한 문자가 아닌 여러 문자들 즉 섹션(또는 그룹)이 0번 또는 1번 나와야 한다는 것을 의미하도록 하는 것이다.

요기 까지는 Syntax 내용이다. 왜 첫번째 글에 넣지 않았냐고.. 장난치냐고… 하면 할 말 엄다. 원문이 그러네..먼 사연이 있겠지…

C# 예제

[Full source]

string InputText = "http://www.yahoo.com/";
string pattern = @"http://(www\.)?([^\.]+)\.com";

Regex exp = new Regex(pattern);
MatchCollection MatchList = exp.Matches(InputText);
Match FirstMatch = MatchList[0];

MessageBox.Show(FirstMatch.Value);

Group GroupCurrent;
for (int i = 1; i < FirstMatch.Groups.Count; i++)
{
GroupCurrent = FirstMatch.Groups[i];
if (GroupCurrent.Success)
{
MessageBox.Show("\tMatched:" + GroupCurrent.Captures[0].Value);
}
else
{
MessageBox.Show("\tGroup didn't match");
}
}


정규표현식 관련 클래스 사용을 위한 using 문 삽입
using System.Text.RegularExpressions;

Regex 클래스는 정규표현식을 나타내는 클래스이다. 정규표현식 패턴은 이 클래스의 생성자에 명시되어야 한다. 그리고 명시된 그 패턴은 변경될 수 없다.

Regex exp = new Regex(@"http://(www\.)?(test\.)?([^\.]+)\.com",
RegexOptions.IgnoreCase);

string InputText = "http://www.yahoo.com/";


MatchCollection 클래스는 입력 문자열 내용 중에서 패턴과 일치하는 내용(결과)(?)들의 목록을 저장하는 클래스이다.

MatchCollection MatchList = exp.Matches(InputText);
Match FirstMatch = MatchList[0];
Console.WriteLine(FirstMatch.Value);


입력문자열에서 패턴에 일치하는 것은 "http://www.yahoo.com" 하나의 경우 이다.

Group 클래스는 Regex 클래스의 패턴내에 존재하는 그룹을 표현하는 클래스이다.
그리고 각 Match 객체는 Groups 컬렉션을 가진다.

Group GroupCurrent;
for (int i = 1; i < FirstMatch.Groups.Count; i++)
{
GroupCurrent = FirstMatch.Groups[i];

FirstMatch가 패턴 일치 결과("http://www.yahoo.com")를 담고 있고 이 결과 문자열 내에서 패턴(@"http://(www\.)?(test\.)?([^\.]+)\.com") 내에 명시된 그룹과 일치하는 항목들이 Groups 컬렉션에 담기게 된다.
그래서 FirstMatch.Groups 의 항목들은 아래의 4개가 된다.

0: http://www.yahoo.com ' 결과 값 자신
1: (www\.) ' "www."와 일치
2. (test\.) ' 일치 없음
3: ([^\.]+) ' "yahoo" 와 일치

Group의 Success 속성은 해당 패턴 내의 Group이 입력문자열에 대하여 일치했는지 아닌지를 확인하는데 사용된다.

if (GroupCurrent.Success)
{
Console.WriteLine("\tMatched:" + GroupCurrent.Captures[0].Value);
}
else
{
Console.WriteLine("\tGroup didn't match");
}
}

Match 내의 Groups는 숫자 또는 이름에 의해 식별될 수 있다.

if (MatchList.Count > 0)
{
if (MatchList[1].Success)
{
Console.WriteLine("Group 1 matched");
}
}


Matches는 또는 일치항목의 섹션이 Regex.Replace()를 이용할 때 대체 표현식으로서 사용되어 질 수 있다.

아래는 추가적으로 알아두어야 할 Syntax 되겠다.

Named Groups(Syntax)
그룹들은 보다 쉬운 식별을 위해 아래의 구문을 통해 이름이 붙여질 수 있다.
(?expression)

단어간의 경계 일치시키기(Syntax)
단어문자(\w) 와 비 단어문자(\W) 간의 경계와 일치시키기 위해서 \b를 사용한다. 일치는 알파벳/숫자가 아닌 문자에 의해 구분되는 단어상의 첫번째 또는 마지막 문자에서 발생한다.

input: Anna Jones and John William-Scott went to lunch- with an anaconda
정규식: \w+\b-\b\w+ : 단어문자가 하나 이상 나오고 단어경계 나오고
"-" 나오고 단언경계 나오고 뒤에 단어문자가 하나이상 나오는 패턴.
Options: IgnoreCase
Matches:
William-Scott

위의 예에서 lunch- with가 match가 될 수 없는 이유는 -(비단어문자) 다음에 다시 비단어문자 공백이 나오기 때문에 \w+\b-\b\w+ 두번째 \b가 일치하지 않는다. "- went"는 비단어문자비단어문자단어문자 이므로 경계는 공백문자와 "w" 사이가 된다. 그러므로 패턴으로 바꾸면, \w+\b-\W\b\w+ 가 되겠다.

\B 는 \b의 반대 즉 경계가 아닌 것을 의미한다.

정규표현식 옵션
- RegexOptions.None - 옵션 없음
- RegexOptions.IgnoreCase - case-insensitive matching.
- RegexOptions.Multiline - Multiline mode. ^과 $의 의미가 전체 문자열의 시작과 끝이 아닌 라인의 끝과 시작을 의미하게 되는것으로 변경된다.
- RegexOptions.Singleline - single-line mode. "."의 의미가 \n을 제외하는 모든 문자에서\n를 제외하지 않는 모든 문자의 의미로 변경된다.
- RegexOptions.ExplicitCapture - 명시적으로 이름이 주언지거나 (?…) 형태를 가지는 그룹만을 유효한 것으로 간주하여 포착한다.(capture)
- RegexOptions.IgnorePatternWhitespace - 패턴에서 이스케이프 되지 않은 공백문자를 제거하고 # 표시로서 주석(comment)을 활성화 한다.
- RegexOptions.Compiled - 정규표현식이 어셈블리로 컴파일 되어 질 것을 명시한다. 정규표현식은 매칭 과정으 더욱 빨리지지만, 초기 컴파일 시간은 더 걸리게 된다.
이 옵션은 for each 구문 등올 통해 표현식이 반복하여 많이 사용되어져야 하는 경우에만 설정하여야 한다.
- RegexOptions.ECMAScript - (정규) 표현식을 위한 ECMAScript 호환을 가지도록 한다.
이 플래그는 반드시 IgnoreCase, Multiline, Compiled 플래그와 결합해서 사용되어 져야 한다. 그렇지 않으면 예외 발생함
- RegexOptions.RightToLeft - 검색이 오른쪽에서 왼쪽 방향으로 되도록 명시
tags :
나의일/.NET 2007/08/10 19:29

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

댓글을 달아 주세요

Powerd by Tistory, designed by criuce
rss