수량자
업데이트: 2010년 10월
수량자는 문자, 그룹 또는 문자 클래스의 인스턴스가 입력에 몇 개 있어야 일치가 검색되는지를 지정합니다. 다음 표에서는 .NET Framework에서 지원하는 수량자를 보여 줍니다.
greedy 수량자 |
lazy 수량자 |
설명 |
---|---|---|
* |
*? |
0개 이상 찾습니다. |
+ |
+? |
0개 또는 한 개 찾습니다. |
? |
?? |
0개 또는 1개 찾습니다. |
{n} |
{n}? |
정확히 n개를 찾습니다. |
{n,} |
{n,}? |
n개 찾습니다. |
{n,m} |
{n,m}? |
n에서 m번 일치시킵니다. |
수량 n 및 m은 정수 상수입니다. 일반적으로 수량자 greedy가 있습니다. 정규식 엔진이 가능한 한 많은 특정 패턴의 발생을 일치시킵니다. ? 문자를 수량자에 추가하면 지연이 발생합니다. 즉, 정규식 엔진이 가능한 적은 발생으로 일치시키게 됩니다. greedy 및 lazy 수량자 사이의 차이점에 대한 자세한 설명은 이 항목 뒷부분의 Greedy 및 Lazy 수량자 단원을 참조하십시오.
중요 |
---|
중첩 수량자(예: 정규식 패턴 (a*)*임)에서는 입력 문자열에서 문자 수의 지수 함수로서 정규식 엔진을 수행해야 하는 비교 수가 늘어날 수 있습니다.이 동작 및 해결 방법에 대한 자세한 내용은 역행 검사을 참조하십시오. |
정규식 수량자
다음 섹션에서는 .NET Framework 정규식에서 지원되는 수량자를 보여 줍니다.
참고 |
---|
*, +, ?, {, and } 문자가 정규식 패턴에 있는 경우 정규식 엔진은 문자 클래스에 포함되지 않은 한 이를 수량자 또는 수량자 구조의 일부로 해석합니다.이를 문자 클래스 이외의 리터럴 문자로 해석하려면 앞에 백슬래시를 입력해야 합니다.예를 들어, 정규식 패턴의 문자열 \*는 리터럴 별표("*") 문자로 해석됩니다. |
0개 이상 찾습니다: *
* 수량자는 이전 요소를 0개 이상 찾습니다. 이는 {0,} 수량자와 같습니다. *는 greedy 수량자이며 해당 lazy 수량자는 *?입니다.
다음 예제에서는 이 정규식을 보여 줍니다. 입력 문자열에 있는 숫자 9개 중 5개가 패턴과 일치하고 4개(95, 929, 9129 및 9919)는 일치하지 않습니다.
Dim pattern As String = "\b91*9*\b"
Dim input As String = "99 95 919 929 9119 9219 999 9919 91119"
For Each match As Match In Regex.Matches(input, pattern)
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
' '99' found at position 0.
' '919' found at position 6.
' '9119' found at position 14.
' '999' found at position 24.
' '91119' found at position 33.
string pattern = @"\b91*9*\b";
string input = "99 95 919 929 9119 9219 999 9919 91119";
foreach (Match match in Regex.Matches(input, pattern))
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);
// The example displays the following output:
// '99' found at position 0.
// '919' found at position 6.
// '9119' found at position 14.
// '999' found at position 24.
// '91119' found at position 33.
이 정규식 패턴은 다음 표에서와 같이 정의됩니다.
패턴 |
설명 |
---|---|
\b |
단어 경계를 시작합니다. |
91* |
9 다음에 0 개 이상의 "1"이 있는 문자를 찾습니다. |
9* |
0개 이상의 "9" 문자를 찾습니다. |
\b |
단어 경계를 종료합니다. |
한 개 이상 찾습니다: +
+ 수량자는 이전 요소를 한 개 이상 찾습니다. 이 옵션은 {1,}와 같습니다. +는 greedy 수량자이며 해당 lazy 수량자는 +?입니다.
예를 들어 정규식 \ban+\w*?\b는 문자 a로 시작하고 뒤에 문자 n이 한 개 이상 나오는 전체 단어를 찾습니다. 다음 예제에서는 이 정규식을 보여 줍니다. 이 정규식은 단어 an, annual, announcement 및 antique와 일치하지만 autumn 및 all과는 일치하지 않습니다.
Dim pattern As String = "\ban+\w*?\b"
Dim input As String = "Autumn is a great time for an annual announcement to all antique collectors."
For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
' 'an' found at position 27.
' 'annual' found at position 30.
' 'announcement' found at position 37.
' 'antique' found at position 57.
string pattern = @"\ban+\w*?\b";
string input = "Autumn is a great time for an annual announcement to all antique collectors.";
foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);
// The example displays the following output:
// 'an' found at position 27.
// 'annual' found at position 30.
// 'announcement' found at position 37.
// 'antique' found at position 57.
이 정규식 패턴은 다음 표에서와 같이 정의됩니다.
패턴 |
설명 |
---|---|
\b |
단어 경계를 시작합니다. |
an+ |
"a" 다음에 하나 이상의 "n" 문자를 찾습니다. |
\w*? |
단어 문자를 0개 이상 찾지만 가능한 적은 개수로 찾습니다. |
\b |
단어 경계를 종료합니다. |
0개 또는 1개 찾습니다: ?
? 수량자는 이전 요소를 0개 또는 한 개 찾습니다. 이 옵션은 {0,1}와 같습니다. ?는 greedy 수량자이며 해당 lazy 수량자는 ??입니다.
예를 들어 정규식 \ban?\b는 문자 a로 시작하고 뒤에 문자 n이 0개 또는 1개 나오는 전체 단어를 찾습니다. 즉, 단어 a 및 an과 일치합니다. 다음 예제에서는 이 정규식을 보여 줍니다.
Dim pattern As String = "\ban?\b"
Dim input As String = "An amiable animal with a large snount and an animated nose."
For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
' 'An' found at position 0.
' 'a' found at position 23.
' 'an' found at position 42.
string pattern = @"\ban?\b";
string input = "An amiable animal with a large snount and an animated nose.";
foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);
// The example displays the following output:
// 'An' found at position 0.
// 'a' found at position 23.
// 'an' found at position 42.
이 정규식 패턴은 다음 표에서와 같이 정의됩니다.
패턴 |
설명 |
---|---|
\b |
단어 경계를 시작합니다. |
an? |
"a" 다음에 0개 또는 한 개 "n" 문자를 찾습니다. |
\b |
단어 경계를 종료합니다. |
정확히 n개 찾습니다: {n}
{n} 수량자는 이전 요소를 정확하게 n번 찾습니다. n은 정수입니다. {n}는 greedy 수량자이며 해당 lazy 수량자는 {n}?입니다.
예를 들어 정규식 \b\d+\,\d{3}\b는 단어 경계 뒤에 숫자가 하나 이상 나오고 그 뒤에 숫자 세 개가 나온 후 단어 경계가 나오는 경우를 찾습니다. 다음 예제에서는 이 정규식을 보여 줍니다.
Dim pattern As String = "\b\d+\,\d{3}\b"
Dim input As String = "Sales totaled 103,524 million in January, " + _
"106,971 million in February, but only " + _
"943 million in March."
For Each match As Match In Regex.Matches(input, pattern)
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
' '103,524' found at position 14.
' '106,971' found at position 45.
string pattern = @"\b\d+\,\d{3}\b";
string input = "Sales totaled 103,524 million in January, " +
"106,971 million in February, but only " +
"943 million in March.";
foreach (Match match in Regex.Matches(input, pattern))
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);
// The example displays the following output:
// '103,524' found at position 14.
// '106,971' found at position 45.
이 정규식 패턴은 다음 표에서와 같이 정의됩니다.
패턴 |
설명 |
---|---|
\b |
단어 경계를 시작합니다. |
\d+ |
하나 이상의 10진수를 찾습니다. |
\, |
쉼표 문자를 찾습니다. |
\d{3} |
세 개의 10진수를 찾습니다. |
\b |
단어 경계를 종료합니다. |
최소 n개 이상 찾습니다: {n,}
{n,} 수량자는 이전 요소를 최소 n번 찾습니다. n은 정수입니다. {n,}는 greedy 수량자이며 해당 lazy 수량자는 {n}?입니다.
예를 들어 정규식 \b\d{2,}\b\D+는 단어 경계 뒤에 최소한 숫자 2개가 나오고 그 뒤에 단어 경계가 나온 후 숫자가 아닌 문자가 나오는 경우를 찾습니다. 다음 예제에서는 이 정규식을 보여 줍니다. "7 days"라는 구는 숫자를 하나만 포함하므로 이 정규식과 일치하지 않지만 "10 weeks and 300 years"라는 구는 정규식과 일치합니다.
Dim pattern As String = "\b\d{2,}\b\D+"
Dim input As String = "7 days, 10 weeks, 300 years"
For Each match As Match In Regex.Matches(input, pattern)
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
' '10 weeks, ' found at position 8.
' '300 years' found at position 18.
string pattern = @"\b\d{2,}\b\D+";
string input = "7 days, 10 weeks, 300 years";
foreach (Match match in Regex.Matches(input, pattern))
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);
// The example displays the following output:
// '10 weeks, ' found at position 8.
// '300 years' found at position 18.
이 정규식 패턴은 다음 표에서와 같이 정의됩니다.
패턴 |
설명 |
---|---|
\b |
단어 경계를 시작합니다. |
\d{2,} |
두 개 이상의 10진수를 찾습니다. |
\b |
단어 경계를 찾습니다. |
\D+ |
하나 이상의 10진수가 아닌 숫자를 찾습니다. |
n개에서 m개 찾습니다: {n, m}
{n,m} 수량자는 이전 요소를 최소 n번, m번은 초과하지 않습니다. n 및 m은 정수입니다. {n,m}는 greedy 수량자이며 해당 lazy 수량자는 {n,m}?입니다.
다음 예제에서는 정규식 (00\s){2,4}는 두 개의 0이 2-4회 나온 후 공백이 나오는 경우를 찾습니다. 입력 문자열의 마지막 부분에는 이 패턴이 최대값인 4회가 아닌 5회 포함되어 있습니다. 그러나 이 부분 문자열의 처음 부분(공백과 다섯 번째 0 쌍)만 정규식 패턴과 일치합니다.
Dim pattern As String = "(00\s){2,4}"
Dim input As String = "0x00 FF 00 00 18 17 FF 00 00 00 21 00 00 00 00 00"
For Each match As Match In Regex.Matches(input, pattern)
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
' '00 00 ' found at position 8.
' '00 00 00 ' found at position 23.
' '00 00 00 00 ' found at position 35.
string pattern = @"(00\s){2,4}";
string input = "0x00 FF 00 00 18 17 FF 00 00 00 21 00 00 00 00 00";
foreach (Match match in Regex.Matches(input, pattern))
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);
// The example displays the following output:
// '00 00 ' found at position 8.
// '00 00 00 ' found at position 23.
// '00 00 00 00 ' found at position 35.
0개 이상 찾습니다(지연 일치): *?
*? 수량자는 이전 요소를 0개 이상 가능한 한 적은 개수로 찾습니다. greedy 수량자 *의 lazy 수량자입니다.
다음 예제에서 \b\w*?oo\w*?\b 정규식은 oo 문자열이 포함된 모든 단어와 일치합니다.
Dim pattern As String = "\b\w*?oo\w*?\b"
Dim input As String = "woof root root rob oof woo woe"
For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
' 'woof' found at position 0.
' 'root' found at position 5.
' 'root' found at position 10.
' 'oof' found at position 19.
' 'woo' found at position 23.
string pattern = @"\b\w*?oo\w*?\b";
string input = "woof root root rob oof woo woe";
foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);
// The example displays the following output:
// 'woof' found at position 0.
// 'root' found at position 5.
// 'root' found at position 10.
// 'oof' found at position 19.
// 'woo' found at position 23.
이 정규식 패턴은 다음 표에서와 같이 정의됩니다.
패턴 |
설명 |
---|---|
\b |
단어 경계를 시작합니다. |
\w*? |
0개 이상의 단어 문자이지만 가능한 적은 문자를 일치시킵니다. |
oo |
문자열 "oo"를 찾습니다. |
\w*? |
0개 이상의 단어 문자이지만 가능한 적은 문자를 일치시킵니다. |
\b |
단어 경계에서 종료합니다. |
0개 또는 한 개 찾습니다(지연 일치): +?
+? 수량자는 이전 요소를 1개 이상 가능한 한 적은 개수로 찾습니다. greedy 수량자 +의 lazy 수량자입니다.
예를 들어 정규식 \b\w+?\b는 단어 경계로 구분된 하나 이상의 문자를 찾습니다. 다음 예제에서는 이 정규식을 보여 줍니다.
Dim pattern As String = "\b\w+?\b"
Dim input As String = "Aa Bb Cc Dd Ee Ff"
For Each match As Match In Regex.Matches(input, pattern)
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
' 'Aa' found at position 0.
' 'Bb' found at position 3.
' 'Cc' found at position 6.
' 'Dd' found at position 9.
' 'Ee' found at position 12.
' 'Ff' found at position 15.
string pattern = @"\b\w+?\b";
string input = "Aa Bb Cc Dd Ee Ff";
foreach (Match match in Regex.Matches(input, pattern))
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);
// The example displays the following output:
// 'Aa' found at position 0.
// 'Bb' found at position 3.
// 'Cc' found at position 6.
// 'Dd' found at position 9.
// 'Ee' found at position 12.
// 'Ff' found at position 15.
0개 또는 한 개 찾습니다(지연 일치): ??
?? 수량자는 이전 요소를 0개 또는 1개 가능한 한 적은 개수로 찾습니다. greedy 수량자 ?의 lazy 수량자입니다.
예를 들어, ^\s*(System.)??Console.Write(Line)??\(?? 정규식은 "Console.Write" 또는 "Console.WriteLine" 문자열을 일치시키려고 시도합니다. 문자열은 "Console" 앞에 "System."도 포함할 수 있으며, 그 다음에 여는 괄호가 올 수 있습니다. 문자열은 줄의 맨 앞에 있어야 하지만 앞에 공백이 나올 수는 있습니다. 다음 예제에서는 이 정규식을 보여 줍니다.
Dim pattern As String = "^\s*(System.)??Console.Write(Line)??\(??"
Dim input As String = "System.Console.WriteLine(""Hello!"")" + vbCrLf + _
"Console.Write(""Hello!"")" + vbCrLf + _
"Console.WriteLine(""Hello!"")" + vbCrLf + _
"Console.ReadLine()" + vbCrLf + _
" Console.WriteLine"
For Each match As Match In Regex.Matches(input, pattern, _
RegexOptions.IgnorePatternWhitespace Or RegexOptions.IgnoreCase Or RegexOptions.MultiLine)
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
' 'System.Console.Write' found at position 0.
' 'Console.Write' found at position 36.
' 'Console.Write' found at position 61.
' ' Console.Write' found at position 110.
string pattern = @"^\s*(System.)??Console.Write(Line)??\(??";
string input = "System.Console.WriteLine(\"Hello!\")\n" +
"Console.Write(\"Hello!\")\n" +
"Console.WriteLine(\"Hello!\")\n" +
"Console.ReadLine()\n" +
" Console.WriteLine";
foreach (Match match in Regex.Matches(input, pattern,
RegexOptions.IgnorePatternWhitespace |
RegexOptions.IgnoreCase |
RegexOptions.Multiline))
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);
// The example displays the following output:
// 'System.Console.Write' found at position 0.
// 'Console.Write' found at position 36.
// 'Console.Write' found at position 61.
// ' Console.Write' found at position 110.
이 정규식 패턴은 다음 표에서와 같이 정의됩니다.
패턴 |
설명 |
---|---|
^ |
입력 스트림의 시작을 찾습니다. |
\s* |
0개 이상의 공백 문자의 일치 여부를 확인합니다. |
(System.)?? |
문자열 "System." 0개 또는 한 개를 찾습니다. |
Console.Write |
문자열 "Console.Write"에 해당합니다. |
(Line)?? |
0 또는 1개의 문자열 "Line"에 해당합니다. |
\(?? |
여는 괄호 0개 또는 한 개를 찾습니다. |
정확히 n개 찾습니다(지연 일치): {n}?
{n}? 수량자는 이전 요소를 정확히 n번 찾습니다. n은 정수입니다. greedy 수량자 {n}+의 lazy 수량자입니다.
다음 예제에서는 웹 사이트 주소를 식별하는 데 \b(\w{3,}?\.){2}?\w{3,}?\b 정규식이 사용되었습니다. "www.microsoft.com" 및 "msdn.microsoft.com"은 찾지만 "mywebsite" 또는 "mycompany.com"은 찾지 못합니다.
Dim pattern As String = "\b(\w{3,}?\.){2}?\w{3,}?\b"
Dim input As String = "www.microsoft.com msdn.microsoft.com mywebsite mycompany.com"
For Each match As Match In Regex.Matches(input, pattern)
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
' 'www.microsoft.com' found at position 0.
' 'msdn.microsoft.com' found at position 18.
string pattern = @"\b(\w{3,}?\.){2}?\w{3,}?\b";
string input = "www.microsoft.com msdn.microsoft.com mywebsite mycompany.com";
foreach (Match match in Regex.Matches(input, pattern))
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);
// The example displays the following output:
// 'www.microsoft.com' found at position 0.
// 'msdn.microsoft.com' found at position 18.
이 정규식 패턴은 다음 표에서와 같이 정의됩니다.
패턴 |
설명 |
---|---|
\b |
단어 경계를 시작합니다. |
(\w{3,}? \.) |
3개 이상의 단어 문자와 일치하지만 가능한 한 적은 수의 문자로 점 또는 기간 문자가 이어집니다. 이 그룹은 첫 번째 캡처링 그룹입니다. |
(\w{3,}? \.){2}? |
첫 번째 그룹의 패턴을 두 번 찾지만 가능한 적게 찾습니다. |
\b |
단어 경계에서 일치 항목 찾기를 끝냅니다. |
최소 n개 이상(지연 일치) 찾습니다: {n,}?
{n,}? 수량자는 이전 요소를 최소 n번 찾습니다. n은 정수이지만 가능한 적은 수입니다. greedy 수량자 {n,}의 lazy 수량자입니다.
이전 단원의 그림에서 {n}? 수량자에 대한 예제를 참조하십시오. 해당 예제의 정규식에서는 {n,} 수량자를 사용하여 최소한 3개의 문자 뒤에 마침표가 나오는 문자열을 찾습니다.
n 및 m 사이를 찾습니다(지연 일치): {n, m}?
{n,m}? 수량자는 이전 요소를 n ~ m번 찾습니다. n 및 m은 정수이지만 가능한 작은 수입니다. greedy 수량자 {n,m}의 lazy 수량자입니다.
다음 예제에서 정규식 \b[A-Z](\w*\s+){1,10}?[.!?]는 단어가 1-10개 들어 있는 문장을 찾습니다. 이 정규식은 입력 문자열에서 단어가 18개 들어 있는 문장 하나를 제외하고 모든 문장과 일치합니다.
Dim pattern As String = "\b[A-Z](\w*\s?){1,10}?[.!?]"
Dim input As String = "Hi. I am writing a short note. Its purpose is " + _
"to test a regular expression that attempts to find " + _
"sentences with ten or fewer words. Most sentences " + _
"in this note are short."
For Each match As Match In Regex.Matches(input, pattern)
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
' 'Hi.' found at position 0.
' 'I am writing a short note.' found at position 4.
' 'Most sentences in this note are short.' found at position 132.
string pattern = @"\b[A-Z](\w*?\s*?){1,10}[.!?]";
string input = "Hi. I am writing a short note. Its purpose is " +
"to test a regular expression that attempts to find " +
"sentences with ten or fewer words. Most sentences " +
"in this note are short.";
foreach (Match match in Regex.Matches(input, pattern))
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);
// The example displays the following output:
// 'Hi.' found at position 0.
// 'I am writing a short note.' found at position 4.
// 'Most sentences in this note are short.' found at position 132.
이 정규식 패턴은 다음 표에서와 같이 정의됩니다.
패턴 |
설명 |
---|---|
\b |
단어 경계를 시작합니다. |
[A-Z] |
A-Z의 대문자를 찾습니다. |
(\w*\s+) |
0개 이상의 문자 다음에 한 개 이상의 공백 문자를 찾습니다. 이 그룹은 첫 번째 캡처링 그룹입니다. |
{1,10}? |
이전 패턴을 1개에서 10개 찾으며, 가능한 한 적은 개수로 찾습니다. |
[.!?] |
문장 부호 문자 ".","!", 또는 "?" 중 하나를 찾습니다. |
Greedy 및 Lazy 수량자
여러 수량자에는 두 가지 버전이 있습니다.
greedy 버전
greedy 수량자는 요소를 찾을 때 최대한 많은 횟수를 적용합니다.
non-greedy 또는 lazy 버전
greedy가 아닌 수량자는 요소를 찾을 때 최대한 적은 횟수를 적용합니다. 단순히 ?를 추가하여 greedy 수량자를 lazy 수량자로 전환할 수 있습니다.
신용 카드 번호와 같은 숫자 문자열에서 마지막 네 숫자를 추출하는 단순한 정규식을 예로 들어 봅니다. * greedy 수량자를 사용하는 정규식 버전은 \b.*([0-9]{4})\b입니다. 그러나 문자열에 숫자가 두 개 들어 있는 경우 이 정규식은 다음 예제와 같이 두 번째 숫자의 마지막 네 숫자만 일치합니다.
Dim greedyPattern As String = "\b.*([0-9]{4})\b"
Dim input1 As String = "1112223333 3992991999"
For Each match As Match In Regex.Matches(input1, greedypattern)
Console.WriteLine("Account ending in ******{0}.", match.Groups(1).Value)
Next
' The example displays the following output:
' Account ending in ******1999.
string greedyPattern = @"\b.*([0-9]{4})\b";
string input1 = "1112223333 3992991999";
foreach (Match match in Regex.Matches(input1, greedyPattern))
Console.WriteLine("Account ending in ******{0}.", match.Groups[1].Value);
// The example displays the following output:
// Account ending in ******1999.
* 수량자는 전체 문자열에서 이전 요소를 최대한 많이 찾으므로 첫 번째 숫자가 정규식과 일치하지 않고 문자열의 끝 부분에서 일치 항목이 검색됩니다.
이는 올바른 동작이 아닙니다. 대신, *? 지연 수량자를 사용하여 다음 예제와 같이 두 번호에서 숫자를 추출할 수 있습니다.
Dim lazyPattern As String = "\b.*?([0-9]{4})\b"
Dim input2 As String = "1112223333 3992991999"
For Each match As Match In Regex.Matches(input2, lazypattern)
Console.WriteLine("Account ending in ******{0}.", match.Groups(1).Value)
Next
' The example displays the following output:
' Account ending in ******3333.
' Account ending in ******1999.
string lazyPattern = @"\b.*?([0-9]{4})\b";
string input2 = "1112223333 3992991999";
foreach (Match match in Regex.Matches(input2, lazyPattern))
Console.WriteLine("Account ending in ******{0}.", match.Groups[1].Value);
// The example displays the following output:
// Account ending in ******3333.
// Account ending in ******1999.
대부분의 경우에는 greedy 수량자와 lazy 수량자를 사용한 정규식에서 동일한 일치 항목을 반환합니다. 서로 다른 결과가 반환되는 가장 일반적인 경우는 모든 문자를 찾는 와일드카드( .) 메타문자가 사용된 경우입니다.
수량자 및 빈 일치 항목
수량자 *, +, {n,m} 및 lazy 수량자는 최소 캡처 수를 찾은 경우 빈 일치 항목이 지나면 반복되지 않습니다. 이 규칙은 가능한 최대 그룹 캡처 수가 무한이거나 무한에 가까울 경우 수량자가 빈 하위 식에 무한 루프를 입력하지 않도록 합니다.
예를 들어, 다음 코드는 0개 또는 1개의 "a" 문자를 0회 이상 일치시키는 정규식 패턴 (a?)*을 사용하여 Regex.Match 메서드에 호출 결과를 보여줍니다. 단일 캡처링 그룹은 String.Empty 외에도 각 "a"를 캡처하지만 첫 번째 빈 일치로 인해 수량자가 반복을 멈추기 때문에 두 번째 빈 일치가 없습니다.
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "(a?)*"
Dim input As String = "aaabbb"
Dim match As Match = Regex.Match(input, pattern)
Console.WriteLine("Match: '{0}' at index {1}",
match.Value, match.Index)
If match.Groups.Count > 1 Then
Dim groups As GroupCollection = match.Groups
For grpCtr As Integer = 1 To groups.Count - 1
Console.WriteLine(" Group {0}: '{1}' at index {2}",
grpCtr,
groups(grpCtr).Value,
groups(grpCtr).Index)
Dim captureCtr As Integer = 0
For Each capture As Capture In groups(grpCtr).Captures
captureCtr += 1
Console.WriteLine(" Capture {0}: '{1}' at index {2}",
captureCtr, capture.Value, capture.Index)
Next
Next
End If
End Sub
End Module
' The example displays the following output:
' Match: 'aaa' at index 0
' Group 1: '' at index 3
' Capture 1: 'a' at index 0
' Capture 2: 'a' at index 1
' Capture 3: 'a' at index 2
' Capture 4: '' at index 3
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = "(a?)*";
string input = "aaabbb";
Match match = Regex.Match(input, pattern);
Console.WriteLine("Match: '{0}' at index {1}",
match.Value, match.Index);
if (match.Groups.Count > 1) {
GroupCollection groups = match.Groups;
for (int grpCtr = 1; grpCtr <= groups.Count - 1; grpCtr++) {
Console.WriteLine(" Group {0}: '{1}' at index {2}",
grpCtr,
groups[grpCtr].Value,
groups[grpCtr].Index);
int captureCtr = 0;
foreach (Capture capture in groups[grpCtr].Captures) {
captureCtr++;
Console.WriteLine(" Capture {0}: '{1}' at index {2}",
captureCtr, capture.Value, capture.Index);
}
}
}
}
}
// The example displays the following output:
// Match: 'aaa' at index 0
// Group 1: '' at index 3
// Capture 1: 'a' at index 0
// Capture 2: 'a' at index 1
// Capture 3: 'a' at index 2
// Capture 4: '' at index 3
캡처의 최소 및 최대 수를 정의하는 캡처 그룹과 고정 캡처 수를 정의하는 캡처 그룹 간의 실질적인 차이를 확인하려면 (a\1|(?(1)\1)){0,2} 및 (a\1|(?(1)\1)){2}의 정규식 패턴을 고려합니다. 두 정규식은 다음 표에 표시된 대로 정의된 단일 캡처링 그룹으로 구성됩니다.
패턴 |
설명 |
---|---|
(a\1 |
첫 번째 캡처 그룹의 값에 따라 "a"와 일치 … |
|(?(1) |
... 또는 첫 번째 캡처된 그룹을 정의했는지 테스트합니다. ((?(1) 구문에서는 캡처링 그룹을 정의하지 않습니다.) |
\1)) |
첫 번째 캡처된 그룹이 있으면 그 값을 일치시킵니다. 그룹이 없으면 이 그룹은 String.Empty와 일치합니다. |
첫 번째 정규식은 0과 두 번 사이에서 이 패턴과 일치하도록 시도하며 두 번째 정규식은 정확히 두 번이 일치하도록 시도합니다. 첫 번째 패턴은 String.Empty의 첫 번째 캡처를 사용하여 최소한의 캡처에 도달하기 때문에 a\1 일치를 찾으려는 시도를 반복하지 않습니다. {0,2} 수량자를 사용하면 마지막 반복에서만 빈 일치가 가능합니다. 이와 반대로 두 번째 정규식은 a\1을(를) 두 번 평가하기 때문에 실제로 "a"와 일치하며 최소 반복 횟수 2는 빈 일치 항목 이후 엔진이 반복되도록 합니다.
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern, input As String
pattern = "(a\1|(?(1)\1)){0,2}"
input = "aaabbb"
Console.WriteLine("Regex pattern: {0}", pattern)
Dim match As Match = Regex.Match(input, pattern)
Console.WriteLine("Match: '{0}' at position {1}.",
match.Value, match.Index)
If match.Groups.Count > 1 Then
For groupCtr As Integer = 1 To match.Groups.Count - 1
Dim group As Group = match.Groups(groupCtr)
Console.WriteLine(" Group: {0}: '{1}' at position {2}.",
groupCtr, group.Value, group.Index)
Dim captureCtr As Integer = 0
For Each capture As Capture In group.Captures
captureCtr += 1
Console.WriteLine(" Capture: {0}: '{1}' at position {2}.",
captureCtr, capture.Value, capture.Index)
Next
Next
End If
Console.WriteLine()
pattern = "(a\1|(?(1)\1)){2}"
Console.WriteLine("Regex pattern: {0}", pattern)
match = Regex.Match(input, pattern)
Console.WriteLine("Matched '{0}' at position {1}.",
match.Value, match.Index)
If match.Groups.Count > 1 Then
For groupCtr As Integer = 1 To match.Groups.Count - 1
Dim group As Group = match.Groups(groupCtr)
Console.WriteLine(" Group: {0}: '{1}' at position {2}.",
groupCtr, group.Value, group.Index)
Dim captureCtr As Integer = 0
For Each capture As Capture In group.Captures
captureCtr += 1
Console.WriteLine(" Capture: {0}: '{1}' at position {2}.",
captureCtr, capture.Value, capture.Index)
Next
Next
End If
End Sub
End Module
' The example displays the following output:
' Regex pattern: (a\1|(?(1)\1)){0,2}
' Match: '' at position 0.
' Group: 1: '' at position 0.
' Capture: 1: '' at position 0.
'
' Regex pattern: (a\1|(?(1)\1)){2}
' Matched 'a' at position 0.
' Group: 1: 'a' at position 0.
' Capture: 1: '' at position 0.
' Capture: 2: 'a' at position 0.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern, input;
pattern = @"(a\1|(?(1)\1)){0,2}";
input = "aaabbb";
Console.WriteLine("Regex pattern: {0}", pattern);
Match match = Regex.Match(input, pattern);
Console.WriteLine("Match: '{0}' at position {1}.",
match.Value, match.Index);
if (match.Groups.Count > 1) {
for (int groupCtr = 1; groupCtr <= match.Groups.Count - 1; groupCtr++)
{
Group group = match.Groups[groupCtr];
Console.WriteLine(" Group: {0}: '{1}' at position {2}.",
groupCtr, group.Value, group.Index);
int captureCtr = 0;
foreach (Capture capture in group.Captures) {
captureCtr++;
Console.WriteLine(" Capture: {0}: '{1}' at position {2}.",
captureCtr, capture.Value, capture.Index);
}
}
}
Console.WriteLine();
pattern = @"(a\1|(?(1)\1)){2}";
Console.WriteLine("Regex pattern: {0}", pattern);
match = Regex.Match(input, pattern);
Console.WriteLine("Matched '{0}' at position {1}.",
match.Value, match.Index);
if (match.Groups.Count > 1) {
for (int groupCtr = 1; groupCtr <= match.Groups.Count - 1; groupCtr++)
{
Group group = match.Groups[groupCtr];
Console.WriteLine(" Group: {0}: '{1}' at position {2}.",
groupCtr, group.Value, group.Index);
int captureCtr = 0;
foreach (Capture capture in group.Captures) {
captureCtr++;
Console.WriteLine(" Capture: {0}: '{1}' at position {2}.",
captureCtr, capture.Value, capture.Index);
}
}
}
}
}
// The example displays the following output:
// Regex pattern: (a\1|(?(1)\1)){0,2}
// Match: '' at position 0.
// Group: 1: '' at position 0.
// Capture: 1: '' at position 0.
//
// Regex pattern: (a\1|(?(1)\1)){2}
// Matched 'a' at position 0.
// Group: 1: 'a' at position 0.
// Capture: 1: '' at position 0.
// Capture: 2: 'a' at position 0.
참고 항목
개념
변경 기록
날짜 |
변경 내용 |
이유 |
---|---|---|
2010년 10월 |
"수량자 및 빈 일치 항목" 섹션을 추가했습니다. |
향상된 기능 관련 정보 |