2013-07-31 7 views
103

이 코드 블록을 이해하려고합니다. 첫 번째 표현에서 우리는 표현에서 무엇을 찾고 있습니까?Java Regex 캡처 그룹

0부터 9까지의 숫자 (1 회 이상 +)와 그 뒤에 임의의 문자 (0 회 이상 *)가 오는 것은 모든 문자 (0 번 이상 *)입니다. 이 결과를 실행

은 다음과 같습니다

Found value: This order was placed for QT3000! OK? 
Found value: This order was placed for QT300 
Found value: 0 

누군가 나와 함께이 통과시겠습니까?

캡처 그룹을 사용하면 어떤 이점이 있습니까?

import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public class RegexTut3 { 

    public static void main(String args[]) { 
     String line = "This order was placed for QT3000! OK?"; 
     String pattern = "(.*)(\\d+)(.*)"; 

     // Create a Pattern object 
     Pattern r = Pattern.compile(pattern); 

     // Now create matcher object. 
     Matcher m = r.matcher(line); 

     if (m.find()) { 
      System.out.println("Found value: " + m.group(0)); 
      System.out.println("Found value: " + m.group(1)); 
      System.out.println("Found value: " + m.group(2)); 
     } else { 
      System.out.println("NO MATCH"); 
     } 
    } 

} 
+0

새 줄을 삽입하려면 줄 끝에 2 개의 공백을 넣으십시오. markdown 구문에 대한 자세한 내용 : http://en.wikipedia.org/wiki/Markdown - 참고 : http : //stackoverflow.com/editing-help – assylias

답변

158

당신이 발생하는 문제는 한정사의 종류입니다 확인. , 그것이 할 수있는 (그리고 어떤 문자이기 때문에, 그것은 거만큼 일치하는 것이다 의미 - 당신은 (인덱스 0 나타내는 전체 Pattern 인덱스 1) 첫 번째 그룹에 욕심 정량을 사용하고 다음 그룹에 대한 조건을 충족시키기 위해 만큼 많은 문자를과 일치시킵니다.

즉, 다음 그룹 \\d+이 일치 할 수있는 한 첫 번째 그룹 .*은 아무거나 일치합니다 (이 경우 마지막 숫자).

세 번째 그룹은 마지막 숫자 다음에 오는 모든 문자와 일치합니다.

당신이 당신의 첫번째 그룹에서 꺼려 정량으로 변경하는 경우, 당신은 당신이 즉, 기대한다고 가정 결과는 일부를 얻을 수 있습니다.

첫 번째 그룹에이라는 의 물음표가 있습니다.

String line = "This order was placed for QT3000! OK?"; 
Pattern pattern = Pattern.compile("(.*?)(\\d+)(.*)"); 
Matcher matcher = pattern.matcher(line); 
while (matcher.find()) { 
    System.out.println("group 1: " + matcher.group(1)); 
    System.out.println("group 2: " + matcher.group(2)); 
    System.out.println("group 3: " + matcher.group(3)); 
} 

출력 : 자바 Patternhere

group 1: This order was placed for QT 
group 2: 3000 
group 3: ! OK? 

더 많은 정보를 원하시면.

마지막으로 캡쳐 그룹은 둥근 괄호로 구분되며 Pattern이 입력과 일치하면 역 참조를 사용하는 매우 유용한 방법을 제공합니다 (다른 것들 중에서도).

Java 6 그룹은 순서 만 참조 할 수 있습니다 (중첩 된 그룹 및 순서 지정에주의하십시오).

Java 7에서는 명명 된 그룹을 사용할 수 있기 때문에 훨씬 쉽습니다.

+0

감사! 이유 그룹 2는 0이 저장 되었는가? 전체 라인이 욕심쟁이 한정 기호에 의해 소비 되었기 때문에 하나 이상의 숫자와 접촉 할 때까지 해제되었습니다. 0이이를 만족 시키므로 표현식이 성공했습니다. 나는 세 번째 그룹이 혼란 스럽다는 것을 알았지 만 욕심쟁이 수량 화 기는 또한 전체 라인을 소비하지만 그 앞에 오는 하나 이상의 숫자 (\\ d +)가 발견 될 때까지지지합니까? – Xivilai

+0

@ Xivilai는 내 대답에서 내 설명을 미세하게 조정 해줍니다. – Mena

+0

그게 좋은 설명입니다. 그래서 마지 못해 왼쪽부터 시작해서 욕심이 많으면 가능한 한 많이 잡을 것입니다 (오른쪽에서 시작). 마지막 숫자 앞에 멈추고 그 조건을 만족시킵니다. 세 번째 그룹은 나머지를 취한다. – Xivilai

3

귀하의 이해가 정확합니다. 그러나, 우리가 걸 으면 :

  • (.*) 전체 문자열을 삼키는 것입니다;
  • (\\d+)이 포화 상태가되도록 백스 타일을 제공해야합니다 (따라서 0이 캡처되고 3000이 아닌 이유입니다).
  • 마지막으로 (.*)은 나머지를 캡처합니다.

그러나 저자의 원래 의도는 무엇인지 확실하지 않습니다. 다큐먼트에서

1

:

Capturing groups</a> are indexed from left 
* to right, starting at one. Group zero denotes the entire pattern, so 
* the expression m.group(0) is equivalent to m.group(). 

그래서 그룹 0 전체 라인을 보낼 캡처합니다.

11

이것은 완전히 정상입니다.

  1. 첫 번째 그룹 (m.group(0))는 항상 정규 표현식 적용되는 전체 영역을 캡처합니다. 이 경우 전체 문자열입니다.
  2. 정규식은 기본적으로 욕심이 있습니다. 즉, 첫 번째 그룹은 정규식을 위반하지 않고 가능한 한 많이 캡처합니다. (.*)(\\d+) (정규 표현식의 첫 번째 부분)은 ...QT300 int는 첫 번째 그룹을 나타내고 0은 초를 나타냅니다.
  3. 첫 번째 그룹을 욕심이 없도록 수정하면 신속하게 해결할 수 있습니다. (.*)(.*?)으로 변경하십시오.

게으른 대 욕심에 대한 추가 정보를 원하시면, this site.