2010-06-04 5 views
7

누구든지 설명 할 수 : 두 패턴이 아래 사용하는 이유자바 매처 그룹 : 차이의 이해 "(: X | Y)"와 "(: X?) | (: Y)"를

  1. 을 다른 결과를 주시겠습니까? (아래 답변 됨)
  2. 두 번째 예제는 그룹 수를 1로 지정하지만 시작은 이고 그룹 1의 끝은 -1이라고하는 이유는 무엇입니까? 다음과 같은 출력을 제공
public void testGroups() throws Exception 
{ 
    String TEST_STRING = "After Yes is group 1 End"; 
    { 
    Pattern p; 
    Matcher m; 
    String pattern="(?:Yes|No)(.*)End"; 
    p=Pattern.compile(pattern); 
    m=p.matcher(TEST_STRING); 
    boolean f=m.find(); 
    int count=m.groupCount(); 
    int start=m.start(1); 
    int end=m.end(1); 

    System.out.println("Pattern=" + pattern + "\t Found=" + f + " Group count=" + count + 
    " Start of group 1=" + start + " End of group 1=" + end); 
    } 

    { 
    Pattern p; 
    Matcher m; 

    String pattern="(?:Yes)|(?:No)(.*)End"; 
    p=Pattern.compile(pattern); 
    m=p.matcher(TEST_STRING); 
    boolean f=m.find(); 
    int count=m.groupCount(); 
    int start=m.start(1); 
    int end=m.end(1); 

    System.out.println("Pattern=" + pattern + "\t Found=" + f + " Group count=" + count + 
    " Start of group 1=" + start + " End of group 1=" + end); 
    } 

}

:

Pattern=(?:Yes|No)(.*)End Found=true Group count=1 Start of group 1=9 End of group 1=21 
Pattern=(?:Yes)|(?:No)(.*)End Found=true Group count=1 Start of group 1=-1 End of group 1=-1

답변

4

요약하기 위해 변경되어야한다.

  • (?:Yes|No)(.*)End 일치 (예 또는 없음) 다음에하지 않는다. * 최종
  • (?:Yes)|(?:No)(.*)End 일치 (예) 또는 (아니 하였다. * 끝)

2) 제 2 패턴이 제공 그룹 수는 1이지만 시작 및 끝은 -1이므로 Matcher 메서드 호출에 의해 반환 된 결과의 (반드시 직관적 일 필요는 없음) 의미 때문입니다. 일치가 발견 된 경우

  • Matcher.find() true를 반환합니다. 귀하의 경우 패턴 일치 부분은 (?:Yes)입니다.
  • Matcher.groupCount()은 캡처 그룹이 실제로 일치 항목에 참여했는지 여부에 관계없이 패턴의 캡처 그룹 수를 반환합니다. 귀하의 경우에는 패턴의 비 캡처 (?:Yes) 부분은 경기에 참가하지만, 그룹 카운트가 1
  • Matcher.start(n)하고 서브의 시작과 끝 인덱스를 반환 Matcher.end(n) 있도록 캡처 (.*) 그룹은 여전히 ​​패턴의 일부 n 번째 캡처 그룹과 일치합니다. 귀하의 경우 전반적인 일치가 발견되었지만 (.*) 캡처 그룹은 경기에 참여하지 않았으므로 하위 시퀀스를 캡처하지 않았으므로 -1 결과가 표시됩니다.

3) (질문 코멘트에 물었다.), 캡처 그룹은 실제로 서브를 캡처 얼마나 많은 결정이 아닌 -1 결과의 수를 계산 Matcher.groupCount() 0에서 Matcher.start(n)을 반복하기 위해. Matcher.start(0)은 전체 패턴을 나타내는 캡처 그룹으로, 귀하의 목적에 따라 제외하고자 할 수도 있습니다.

7
  1. 차이는 제 2 패턴 "(?:Yes)|(?:No)(.*)End"에서, 연결은 ("XY"에서 "X가 Y 뒤에")이다 ("X | Y"에서 "X 또는 Y 중 어느 하나"보다) precedence이 더 높습니다. 곱셈은 더하기보다 우선 순위가 높으므로 패턴은

    와 같습니다.

    "(?:(?:Yes)|(?:No))(.*)End" 
    

    이 첫 번째 패턴과 같은 출력을 얻을 수 : 당신이 얻을 싶어 무엇는

    "(?:Yes)|(?:(?:No)(.*)End)" 
    

    다음과 같은 패턴이다.

    테스트에서 두 번째 패턴의 그룹 1은 (공백) 범위 [-1, -1[이므로 일치하지 않습니다 (시작 -1이 포함되고 끝 -1이 제외되어 half-open interval이 비어 있음).

  2. 는 캡처 그룹은 그룹수도 캡처 입력된다. 캡처 할 경우 입력의 일부 하위 문자열과 일치한다고 말합니다. 정규식에 선택 항목이 포함되어 있으면 모든 캡처 그룹이 실제로 입력을 캡처하지 않을 수 있으므로 정규식이 일치하더라도 일치하지 않는 그룹이있을 수 있습니다. Matcher.groupCount()에 의해 반환

  3. 그룹 수

    는 관계없이 그 중 하나는 주어진 입력에 일치 할 수 있는지의 캡처 그룹의 그룹화 괄호 을 계산하여 순수하게 얻어진다. 패턴에는 정확히 하나의 캡처 그룹이 있습니다 : (.*).

    (?:X) X, as a non-capturing group 
    

    explains :이 그룹 1 documentation states입니다 (?로 시작

    그룹 텍스트를 캡처하지 않고 그룹 전체에 포함되지 않는 순수한, 비 캡처 그룹 중 하나는, 또는 명명 된 캡처 그룹.

    주어진 입력에 특정 그룹이 일치하는지 여부는 해당 정의와 관련이 없습니다. 예를 들어, 패턴 (Yes)|(No)에는 두 개의 그룹 ((Yes)은 그룹 1, 그룹 2는 (No))이지만 주어진 입력에 대해 하나만 일치 할 수 있습니다.

  4. Matcher.find()을 호출하면 일부 문자열에서 정규 표현식이 일치하면 true가 반환됩니다.시작을보고 일치하는 그룹을 판별 할 수 있습니다. -1 일 경우 그룹이 일치하지 않습니다. 이 경우 끝은 -1입니다. find() 또는 match()을 호출 한 후 실제로 일치하는 캡처 그룹 수를 알려주는 기본 제공 방법은 없습니다. 당신은 각 그룹의 시작을 보면서 자신을 계산해야합니다.

  5. 은 역 참조에 관해서, 또한 the regex tutorial 말을 무슨주의 :

    아무것도 일치하지 캡처 그룹에 대한 역 참조 사이에 차이가 있으며, 했던 캡처 그룹에 하나 경기에 전혀 참가하지 않는다.

+0

고맙습니다. 나는 여전히 그룹 수 (group count)가 1 인 이유를 이해하고 싶습니다. (1 권의 그룹 수는 하나의 번호가 매겨진 그룹이 발견되어 시작해야 함을 (문서 및 기타 실험을 통해) 이해했습니다. 1. – user358795

+0

그룹 수는 그룹 대괄호를 계산하여 순전히 얻고 패턴에는 정확히 하나 ('. * ')가 있습니다. 이것은 그룹 1입니다. 특정 그룹이 주어진 입력과 일치하는지 여부는 해당 정의와 관련이 없습니다. 예를 들어 패턴 ""(예) | (아니오) "'에 두 그룹이 있습니다 ("(예) "는 그룹 1,"(아니오) "는 그룹 2). 주어진 입력. –

+1

그래서 문서에 "이 정규 표현식 패턴의 캡처 그룹 수를 반환합니다."라고 쓰여 있습니다. 일치가없는 경우에도 표현식의 수를 의미합니까? 이 경우 find() 호출이 true를 반환하는 이유는 무엇입니까? 또는 다른 방법으로 말하자면, 어떤 그룹이 일치하는지 그리고 얼마나 많은 그룹이 일치 하는지를 결정하는 방법은 무엇입니까? – user358795

3

"|" 당신이 원하는 무엇

(?:Yes)|((?:No)(.*)End) 

(?:(?:Yes)|(?:No))(.*)End 
+0

Javadoc에서 분명히 설명하고있는 것처럼 groupCount가 잘못되었습니다. * 그룹 0은 규칙에 따라 전체 패턴을 나타냅니다. 이 숫자에는 ** ** 포함되어 있지 않습니다. * 직관적이지 않습니다. –

+0

Ack .. 나는 대답이 잘못되어 틀렸다. – jimr

1

정규 표현식을 사용하는 것이 중요 거기에 기억 암시 AND 작업자가 작업에 존재입니다 :에 패턴 연산자는 두 번째 패턴은 동일합니다. 이것은 java.util.regex.Pattern 덮는 논리 연산자위한 Javadoc로부터 알 수 : Y
하였다

논리 연산자
XY X X | 포착로서 Y 어느 X 또는 Y
(X) X, 그룹은

AND은 제 2 패턴에 OR 우선합니다. 두 번째 패턴은
(?:Yes)|(?:(?:No)(.*)End)과 같습니다. 이 제 1 패턴에 해당 되려면

1) 두 패턴들 때문에 운영자의 우선 순위 규칙의 다른 결과를,
(?:(?:Yes)|(?:No))(.*)End

관련 문제