.NET의 정규 표현식 언어와 관련하여 “그룹”과 “캡처”의 차이점이 무엇인지 조금 모호합니다. 다음 C # 코드를 고려하십시오.
MatchCollection matches = Regex.Matches("{Q}", @"^\{([A-Z])\}$");
나는 이것이 문자 ‘Q’에 대한 단일 캡처를 초래할 것으로 기대하지만 반환 된 속성을 인쇄하면 MatchCollection
다음을 볼 수 있습니다.
matches.Count: 1
matches[0].Value: {Q}
matches[0].Captures.Count: 1
matches[0].Captures[0].Value: {Q}
matches[0].Groups.Count: 2
matches[0].Groups[0].Value: {Q}
matches[0].Groups[0].Captures.Count: 1
matches[0].Groups[0].Captures[0].Value: {Q}
matches[0].Groups[1].Value: Q
matches[0].Groups[1].Captures.Count: 1
matches[0].Groups[1].Captures[0].Value: Q
여기서 정확히 무슨 일이 일어나고 있습니까? 나는 전체 경기에 대한 캡처가 있다는 것을 이해하지만 그룹은 어떻게 들어 옵니까? 왜 matches[0].Captures
문자 ‘Q’에 대한 캡처를 포함 하지 않습니까?
답변
처음 퍼지 한 사람은 아닙니다. 다음은 유명한 Jeffrey Friedl의 의견입니다 (437 페이지 이상).
보기에 따라 일치하는 결과에 흥미로운 새로운 차원이 추가되거나 혼란과 팽창이 추가됩니다.
그리고 더 :
Group 개체와 Capture 개체의 주요 차이점은 각 Group 개체에는 일치하는 동안 그룹이 일치하는 모든 중간 일치 항목과 그룹과 일치하는 최종 텍스트를 나타내는 캡처 모음이 포함되어 있다는 것입니다 .
그리고 몇 페이지 후, 이것이 그의 결론입니다.
.NET 문서를 지나서 실제로 이러한 개체가 무엇을 추가하는지 이해 한 후에는 그에 대한 감정이 혼동되었습니다. 한편으로는 흥미로운 혁신 [..]이며 대부분의 경우에 사용되지 않는 기능의 효율성 부담 [..]을 추가하는 것으로 보입니다.
다시 말해서 : 그것들은 매우 유사하지만, 때때로 그리고 그것이 일어날 때, 그것들을 사용할 수 있습니다. 또 다른 회색 수염을 키우기 전에 캡처를 좋아할 수도 있습니다 …
위의 내용이나 다른 게시물에서 언급 한 내용이 실제로 귀하의 질문에 대답하지 않는 것 같으므로 다음을 고려하십시오. 캡처는 일종의 기록 추적기로 생각하십시오. 정규 표현식이 일치하면 왼쪽에서 오른쪽으로 문자열을 통과하고 (순간 역 추적 무시) 일치하는 괄호를 발견하면 $x
(x는 모든 숫자 임) 에 저장합니다 $1
.
캡처 괄호를 반복 할 때 일반 정규식 엔진은 전류를 버리고 $1
새 값으로 대체합니다. .NET이 아닙니다.이 기록을 유지하고에 저장합니다 Captures[0]
.
정규식을 다음과 같이 변경하면 :
MatchCollection matches = Regex.Matches("{Q}{R}{S}", @"(\{[A-Z]\})+");
첫 번째는 것을 알 Group
한 것 Captures
(첫 번째 그룹 항상 동일, 즉, 전체 일치되는 $0
)과 두 번째 그룹이 개최 {S}
즉 마지막 일치하는 그룹. 그러나 여기에 캐치가 있습니다. 다른 두 캐치를 찾으려면 및에 Captures
대한 모든 중간 캡처가 포함 된에 있습니다 .{Q}
{R}
{S}
문자열에 명확하게있는 개별 캡처와의 마지막 일치 만 표시하는 다중 캡처에서 얻을 수있는 방법에 대해 궁금한 경우을 사용해야합니다 Captures
.
최종 질문에 대한 마지막 단어 : 총 일치는 항상 총 캡처가 하나이므로 개별 그룹과 혼합하지 마십시오. 캡처는 그룹 내에서만 흥미 롭습니다 .
답변
그룹은 정규 표현식에서 그룹과 관련이있는 것입니다.
"(a[zx](b?))"
Applied to "axb" returns an array of 3 groups:
group 0: axb, the entire match.
group 1: axb, the first group matched.
group 2: b, the second group matched.
이것들은 단지 ‘포획 된’그룹이라는 것을 제외하고. 캡처하지 않은 그룹 ( ‘(? :’구문 사용)은 여기에 표시되지 않습니다.
"(a[zx](?:b?))"
Applied to "axb" returns an array of 2 groups:
group 0: axb, the entire match.
group 1: axb, the first group matched.
캡처는 또한 ‘캡처 된 그룹’과 관련된 것입니다. 그러나 그룹에 수량자를 여러 번 적용하면 마지막 일치 만 그룹의 일치로 유지됩니다. 캡처 배열은 이러한 모든 일치 항목을 저장합니다.
"(a[zx]\s+)+"
Applied to "ax az ax" returns an array of 2 captures of the second group.
group 1, capture 0 "ax "
group 1, capture 1 "az "
마지막 질문에 관해서는-Captures는 그들이 속한 그룹이 주문한 캡처의 배열이라고 생각했습니다. 오히려 이것은 그룹 [0] .Captures의 별명 일뿐입니다. 무용지물 ..
답변
간단한 예 (그림)로 설명 할 수 있습니다.
3:10pm
정규식과 일치 하고 ((\d)+):((\d)+)(am|pm)
Mono 대화식 사용 csharp
:
csharp> Regex.Match("3:10pm", @"((\d)+):((\d)+)(am|pm)").
> Groups.Cast<Group>().
> Zip(Enumerable.Range(0, int.MaxValue), (g, n) => "[" + n + "] " + g);
{ "[0] 3:10pm", "[1] 3", "[2] 3", "[3] 10", "[4] 0", "[5] pm" }
네 번째 그룹에는 일치하는 여러 자릿수가 있으므로 그룹을 참조하는 경우 ( ToString()
즉 , 암시 적 으로) 마지막 일치 만 “얻습니다” . 중간 일치 항목을 공개하려면 Captures
해당 그룹 의 속성을 더 깊이 살펴보고 참조해야합니다 .
csharp> Regex.Match("3:10pm", @"((\d)+):((\d)+)(am|pm)").
> Groups.Cast<Group>().
> Skip(4).First().Captures.Cast<Capture>().
> Zip(Enumerable.Range(0, int.MaxValue), (c, n) => "["+n+"] " + c);
{ "[0] 1", "[1] 0" }
이 기사의 의례 .
답변
MSDN 설명서에서 :
Captures 속성의 실제 유틸리티는 한정 그룹이 캡처 그룹에 적용되어 그룹이 단일 정규식으로 여러 하위 문자열을 캡처 할 때 발생합니다. 이 경우 Group 객체에는 마지막으로 캡처 된 하위 문자열에 대한 정보가 포함되고 Captures 속성에는 그룹이 캡처 한 모든 하위 문자열에 대한 정보가 포함됩니다. 다음 예에서는 정규식 \ b (\ w + \ s *) +입니다. 마침표로 끝나는 전체 문장과 일치합니다. 그룹 (\ w + \ s *) +은 모음의 개별 단어를 캡처합니다. Group 컬렉션에는 마지막으로 캡처 된 하위 문자열에 대한 정보 만 포함되므로 “문장”문장의 마지막 단어를 캡처합니다. 그러나 그룹에서 캡처 한 각 단어는 Captures 속성이 반환 한 컬렉션에서 사용할 수 있습니다.
답변
다음과 같은 텍스트 입력 dogcatcatcat
과 같은 패턴 이 있다고 상상해보십시오.dog(cat(catcat))
이 경우 그룹이 3 개이며 첫 번째 그룹 ( 주요 그룹 )이 일치합니다.
일치 == dogcatcatcat
및 Group0 ==dogcatcatcat
Group1 == catcatcat
Group2 == catcat
무슨 일이야?
Regex
클래스를 사용하여 C # (. NET)으로 작성된 작은 예제를 살펴 보겠습니다 .
int matchIndex = 0;
int groupIndex = 0;
int captureIndex = 0;
foreach (Match match in Regex.Matches(
"dogcatabcdefghidogcatkjlmnopqr", // input
@"(dog(cat(...)(...)(...)))") // pattern
)
{
Console.Out.WriteLine($"match{matchIndex++} = {match}");
foreach (Group @group in match.Groups)
{
Console.Out.WriteLine($"\tgroup{groupIndex++} = {@group}");
foreach (Capture capture in @group.Captures)
{
Console.Out.WriteLine($"\t\tcapture{captureIndex++} = {capture}");
}
captureIndex = 0;
}
groupIndex = 0;
Console.Out.WriteLine();
}
출력 :
match0 = dogcatabcdefghi
group0 = dogcatabcdefghi
capture0 = dogcatabcdefghi
group1 = dogcatabcdefghi
capture0 = dogcatabcdefghi
group2 = catabcdefghi
capture0 = catabcdefghi
group3 = abc
capture0 = abc
group4 = def
capture0 = def
group5 = ghi
capture0 = ghi
match1 = dogcatkjlmnopqr
group0 = dogcatkjlmnopqr
capture0 = dogcatkjlmnopqr
group1 = dogcatkjlmnopqr
capture0 = dogcatkjlmnopqr
group2 = catkjlmnopqr
capture0 = catkjlmnopqr
group3 = kjl
capture0 = kjl
group4 = mno
capture0 = mno
group5 = pqr
capture0 = pqr
첫 번째 일치 항목 ( match0
) 만 분석하겠습니다 .
당신이 볼 수 있듯이이 세 가지 있습니다 작은 그룹은 : group3
, group4
및group5
group3 = kjl
capture0 = kjl
group4 = mno
capture0 = mno
group5 = pqr
capture0 = pqr
이러한 그룹 (3-5)은 기본 패턴 의 ‘ 서브 패턴 ‘ (...)(...)(...)
으로 인해 생성되었습니다. (dog(cat(...)(...)(...)))
의 값은 group3
캡처 ( capture0
) 에 해당합니다 . ( group4
및 의 경우 와 같이 group5
). 같은 그룹 반복이 없기 때문 (...){3}
입니다.
자, 그룹 반복 이있는 또 다른 예를 생각해 봅시다 .
우리가에서 (코드 위의 그림에 대한) 일치하는 정규 표현식 패턴을 수정하는 경우 (dog(cat(...)(...)(...)))
에 (dog(cat(...){3}))
, 다음이 있음을 알 수 있습니다 그룹 반복 : (...){3}
.
이제 출력 이 변경되었습니다.
match0 = dogcatabcdefghi
group0 = dogcatabcdefghi
capture0 = dogcatabcdefghi
group1 = dogcatabcdefghi
capture0 = dogcatabcdefghi
group2 = catabcdefghi
capture0 = catabcdefghi
group3 = ghi
capture0 = abc
capture1 = def
capture2 = ghi
match1 = dogcatkjlmnopqr
group0 = dogcatkjlmnopqr
capture0 = dogcatkjlmnopqr
group1 = dogcatkjlmnopqr
capture0 = dogcatkjlmnopqr
group2 = catkjlmnopqr
capture0 = catkjlmnopqr
group3 = pqr
capture0 = kjl
capture1 = mno
capture2 = pqr
다시, 첫 번째 일치 ( match0
) 만 분석해 봅시다 .
이보다 더없는 작은 그룹 group4
및 group5
때문에 (...){3}
반복 ( {N} 항에있어서, N> = 2 )가 있었던 하나 개의 단일 그룹으로 병합 group3
.
이 경우 group3
값은 해당 값에 해당합니다 capture2
( 즉, 마지막 캡처 ).
당신은 모든 3 내부 캡처를 필요 따라서 경우에 ( capture0
, capture1
, capture2
) 당신은 그룹의 순환해야 Captures
모음입니다.
결론 : 패턴 그룹을 디자인하는 방식에주의하십시오. 당신은 행동이 같은 그룹의 사양의 원인을 선불로 생각해야한다 (...)(...)
, (...){2}
또는 (.{3}){2}
등
바라건대 Captures , Groups 및 Matches 의 차이점에 대한 정보를 얻을 수 있기를 바랍니다 .