Writter by Youngil Kim, C#.NET Developer
특정 문자열에서 특정 패턴에 맞는 부분문자열을 뽑아내는 방법에 대해서 정규식을 이용하는 방법을 정리해보겠습니다. (사실 저도 가끔써먹을때가 있는데 정리해두면 좋을것같아성)
예로 HTML에서 가장많이 사용하는 형태로,
<a href="URL" ~>링크</a>
와 같은 앵커요소에 대해서 URL과 텍스트부분을 얻고자 한다면 다음과 같이 정규식으로 표현할 수 있습니다.
<a href="(?<url>.*?)".*?>(?<text>.*?)</a>
( 와 )로 둘러쌓인 부분은 그룹화를 하고 있어 각각 ?<url>, ?<text>에 의하여 url과 text라고 그룹명을 붙여 있고 .*?라는 부분은 최단일치를 지정하는 것으로 .*?>는 >이외의 임의의 문자를 나란히 + > ,를 나타내는 형태입니다.
- Regex 객체 만들기
먼저, 정규식을 사용하게 해주는 System.Text.RegularExpressions네임스페이스의 Regex클래스의 객체를 만듭니다.
Regex rg = new Regex("<a href=\"(?<url>.*?)\".*?>(?<text>.*?)</a>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
위에서 2개의 파라미터로 2개의 옵션을 지정하는데 RegexOptions.IgnoreCase는 대소문자 구별없이 매치시키는 것으로 이것에 의해 <A HREF=.....>일 것이라는 앵커요소에도 매치됩니다. RegexOptions.Singleline는 임의의 1문자를 나타내며 . 을 개행문자에도 매치시키기 위한 것으로 1개의 앵커요소가 여러행에 걸쳐서 있어도 매치하게 됩니다.
- Match 객체 얻기
다음으로 매칭을 실행하고 처음에 매치된 부분을 System.Text.RegularExpressions네임스페이스의 Match클래스의 객체로서 얻습니다. 이것에는 Regex객체의 Match메소드를 호출합니다. Match메소드의 파라미터에는 검색대상으로 된 텍스트를 문자열로 지정합니다. 이 예제에서는 HTML의 내용이라고 보시면 될것같네요.
Match m = reg.Match(<검색대상으로 된 문자열>);
단, 매치된 부분이 검색대생에 존재하지 않으면 Match객체의 Success속성이 false로 됩니다. 2번째 매치된 부분은 이와 같이 얻어진 Match객체에 대해 NextMatch메소드를 호출하여 얻습니다.
m = m.NextMatch();
이 경우에도 Success속성에 의해 매치한 부분이 존재하는지 확인할 필요가 있습니다. 이후 줄줄이 NextMatch 메소드를 호출하면서 모든 매치된 부분을 순서대로 얻을 수 있습니다.
- Match 객체로부터 그룹화한 부분 얻기
Match객체는 정규식에 매치한 부분 문자열전체를 가지고 있지만, 정규식에 그룹화를 한 경우, 그 문자열로부터 그룹화한 부분만 얻을 수 있습니다. 이것에는 다음과 같이 Match객체의 Groups속성으로 그룹명을 지정하여 해당 Value속성에 접근할 수 있습니다.
string url = m.Groups["url"].Value;
string text = m.Groups["text"].Value;
정규식내 그룹에 이름을 붙여 있지 않는 경우, 자동적으로 거절당한 번호에 의해 Groups속성에 접근한 것이 되지만, 이름을 붙인 쪽이 코드를 읽기 쉽게 됩니다.
[예제]
이 예제는 네이버의 메인페이지를 읽고 해당 HTML로부터 앵커요소에 포함된 URL부분과 링크문자열부분을 분리하여 보여줍니다.
using System;
using System.Net;
using System.Text.RegularExpressions;
class RegexMatch {
static void Main() {
string anchor = "<a href=\"(?<url>.*?)\".*?>(?<text>.*?)</a>";
WebClient wc = new WebClient();
string html = wc.DownloadString("http://www.naver.com/");
Regex re = new Regex(anchor, RegexOptions.IgnoreCase | RegexOptions.Singleline);
for(Match m = re.Match(html); m.Success; m=m.NextMatch()) {
string url = m.Groups["url"].Value;
string text = m.Groups["text"].Value;
Console.WriteLine(url);
Console.WriteLine(text);
}
}
}
방법: 정규식을 사용하여 문자열 검색(C# 프로그래밍 가이드)
System.Text.RegularExpressions.Regex 클래스를 사용하여 문자열을 검색할 수 있습니다. 매우 단순한 검색에서 정규식을 최대한 활용하는 매우 복잡한 검색까지 다양한 검색을 수행할 수 있습니다. 다음 두 예제에서는 Regex 클래스를 사용하여 문자열을 검색하는 방법을 보여 줍니다. 자세한 내용은 .NET Framework 정규식을 참조하십시오.
예제
class TestRegularExpressions
{
static void Main()
{
string[] sentences =
{
"cow over the moon",
"Betsy the Cow",
"cowering in the corner",
"no match here"
};
string sPattern = "cow";
foreach (string s in sentences)
{
System.Console.Write("{0,24}", s);
if (System.Text.RegularExpressions.Regex.IsMatch(s, sPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase))
{
System.Console.WriteLine(" (match for '{0}' found)", sPattern);
}
else
{
System.Console.WriteLine();
}
}
}
}
출력
cow over the moon (match for 'cow' found)
Betsy the Cow (match for 'cow' found)
cowering in the corner (match for 'cow' found)
no match here다음 코드는 정규식을 사용하여 배열에서 각 문자열 형식의 유효성을 검사하는 콘솔 응용 프로그램입니다. 유효성 검사를 통과하려면 각 문자열의 형식이 전화 번호와 같아야 합니다. 즉 세 그룹의 숫자가 대시(-)로 구분되어야 하고 처음 두 그룹에는 세 개, 세 번째 그룹에는 네 개의 숫자가 있어야 합니다. ^\\d{3}-\\d{3}-\\d{4}$와 같은 정규식을 사용하면 이를 수행할 수 있습니다. 자세한 내용은 정규식 언어 요소를 참조하십시오.
class TestRegularExpressionValidation
{
static void Main()
{
string[] numbers =
{
"123-456-7890",
"444-234-22450",
"690-203-6578",
"146-893-232",
"146-839-2322",
"4007-295-1111",
"407-295-1111",
"407-2-5555",
};
string sPattern = "^\\d{3}-\\d{3}-\\d{4}$";
foreach (string s in numbers)
{
System.Console.Write("{0,14}", s);
if (System.Text.RegularExpressions.Regex.IsMatch(s, sPattern))
{
System.Console.WriteLine(" - valid");
}
else
{
System.Console.WriteLine(" - invalid");
}
}
}
}
출력
123-456-7890 - valid
444-234-22450 - invalid
690-203-6578 - valid
146-893-232 - invalid
146-839-2322 - valid
4007-295-1111 - invalid
407-295-1111 - valid
407-2-5555 - invalid