문자열에서 특정패턴에 맞는 문자열을 추출하고 싶을때 유용하다.
예를 들어 아래 공식 예제를 풀이해보자면
private static void DumpHRefs(string inputString)
{
Match m;
string HRefPattern = @"href\s*=\s*(?:[""'](?<1>[^""']*)[""']|(?<1>\S+))";
try
{
m = Regex.Match(inputString, HRefPattern,
RegexOptions.IgnoreCase | RegexOptions.Compiled,
TimeSpan.FromSeconds(1));
while (m.Success)
{
Console.WriteLine("Found href " + m.Groups[1] + " at "
+ m.Groups[1].Index);
m = m.NextMatch();
}
}
catch (RegexMatchTimeoutException)
{
Console.WriteLine("The matching operation timed out.");
}
}
public static void Main()
{
string inputString = "My favorite web sites include:</P>" +
"<A HREF=\"http://msdn2.microsoft.com\">" +
"MSDN Home Page</A></P>" +
"<A HREF=\"http://www.microsoft.com\">" +
"Microsoft Corporation Home Page</A></P>" +
"<A HREF=\"http://blogs.msdn.com/bclteam\">" +
".NET Base Class Library blog</A></P>";
DumpHRefs(inputString);
}
// The example displays the following output:
// Found href http://msdn2.microsoft.com at 43
// Found href http://www.microsoft.com at 102
// Found href http://blogs.msdn.com/bclteam at 176
목표는 주어진 문자열에서 url 주소를 가져오는 것
주어진 문자열
My favorite web sites include:</P>
<A HREF="http://msdn2.microsoft.com">
MSDN Home Page</A></P>
<A HREF="http://www.microsoft.com">
Microsoft Corporation Home Page</A></P>
<A HREF="http://blogs.msdn.com/bclteam">
.NET Base Class Library blog</A></P>
이에 대한 정규식은
href\s*=\s*(?:[""'](?<1>[^""']*)[""']|(?<1>\S+))
분석하자면
href : 문자열"href"와 일치함을 의미한다. 원래는 대소문자를 구분하기에 위의 예제에 맞추려면 대문자 HREF가 되어야 하지만 Match() 함수에 IgnoreCase 옵션을 넣었기에 소문자도 ok.
\s : 's'는 space. 즉 공백문자와 일치함을 의미한다.
* : 앞에 위치한 문자의 0~n번 반복을 의미한다. 즉 \s* 는 공백문자가 0~n번 반복됨을 의미한다.
= : 문자'='와 일치함을 의미한다.
(?:[""'](?<1>[^""']*)[""']|(?<1>\S+)) : 여러 식이 조합되어 있다. (?:expression1|expression2) 형태로 이해하면 된다.
(expression) : 그룹화 캡쳐를 의미한다. 괄호 내부에 선언된 식에 의해 추출된 데이터를 따로 캡쳐해둔다. 캡쳐된 데이터는
Match m = Regex.Match(input, expression);
string capture1 = m.Groups[1].Value;
string capture2 = m.Groups[2].Value;
이런 식으로 사용할 수 있다.(?:expression) : ?: 는 그룹화는 하지만 캡쳐는 안하겠다는 의미이다. 캡쳐안하는데 그룹화를 하는 이유는 | 를 사용하기 위함이다.
(?:expression1|expression2) : expression1 와 일치하거나 expression2 와 일치하는 문자열을 찾는다.
expression1 [""'](?<1>[^""']*)[""'] 를 분석하자면
[""'] : 본래는 ["'] 인데 코드문법상 " 를 "" 로 표기한 것. [ ] 는 괄호 내부 문자들 중에 하나라도 있다면 일치함을 의미한다. 예를 들어 [abc]는 'a','b','c' 중 하나라도 있다면 일치함을 의미한다. 즉 ["'] 는 " 또는 ' 와 일치함을 의미한다.
(?<1>[^""']*) : (?<1>expression) 는 캡쳐된 데이터를 배열 1번째에 할당하겠다는 의미이다. [^""'] 는 [""'] 의 반대이다. ^ 는 뒤에 위치한 문자를 제외한 나머지를 의미하기에 [^""'] 는 " 와 ' 를 제외한 아무 문자와 일치함을 의미한다.
결국 expression1 [""'](?<1>[^""']*)[""'] 은 ""와'를제외한아무문자열" 또는 '"와'를제외한아무문자열' 를 의미한다. 그리고 배열1번째에 캡쳐되는 문자열은 "와'를제외한아무문자열 이 된다.
expression2 (?<1>\S+)를 분석하자면
\S : \s 의 반대다. 공백이 아닌 문자와 일치함을 의미한다.
+ : * 가 앞의 위치한 문자의 0~n번 반복을 의미한다면, + 는 앞의 위치한 문자의 1~n번 반복을 의미한다.
결국 expression2 (?<1>\S+)는 공백이아닌아무문자열 을 의미하며 이를 배열1번째에 캡쳐하겠다는 의미이다.
정리하자면
정규식 href\s*=\s*(?:[""'](?<1>[^""']*)[""']|(?<1>\S+)) 는 주어진 문자열에서
href(공백0개이상)=(공백0개이상)(("또는')("와'를제외한아무문자열)("또는')or(공백이아닌아무문자열)) 를 찾는다.
예1) <a href = 'urlstring'> 에서 정규식과 일치하는 문자열은
href = 'urlstring' 이고 캡쳐된 데이터는 urlstring 이다.
예2) hdsaghref= "sg aijgsli 2357*2"gefa 에서 정규식과 일치하는 문자열은
href= "sg aijgsli 2357*2" 이고 캡쳐된 데이터는 sg aijgsli 2357*2 이다.
사실 위의 ms 예제코드만 가지고 보자면
정규식은 href\s*=\s*[""'](?<1>[^""']*)[""'] 으로 충분하다.
예제 코드에서 href\s*=\s*(?:[""'](?<1>[^""']*)[""']|(?<1>\S+))를 사용한 이유는
url 이 "또는' 문자로 안 묶여있는 패턴 (예: href=http://www.microsoft.com ) 을 찾기 위함인 것 같다.
c# 뿐 아니라 java난 python 등 대부분의 언어에서 정규식을 지원하고 있다.
사용법은 거의 비슷하나 언어마다 약간의 차이가 있으니 확인하도록 하자.
댓글 없음:
댓글 쓰기