Java 정규식 캡처 그룹 색인


113

다음 줄이 있습니다.

typeName="ABC:xxxxx;";

단어를 가져와야합니다 ABC.

다음 코드 스 니펫을 작성했습니다.

Pattern pattern4=Pattern.compile("(.*):");
matcher=pattern4.matcher(typeName);

String nameStr="";
if(matcher.find())
{
    nameStr=matcher.group(1);

}

그래서 넣으면 group(0)내가 얻을 ABC:하지만 난 세우면 group(1)그것은이다 ABC내가 알고 싶은, 그래서

  1. 이 무엇을 않습니다 01의미? 누구든지 좋은 예를 들어 설명해 주시면 더 좋을 것입니다.

  2. 정규식 패턴에이 포함되어 있는데 :group(1)결과가 생략됩니까? 그룹 1은 괄호 안의 모든 단어를 감지합니까?

  3. 그래서 괄호를 두 개 더 넣으면 \\s*(\d*)(.*): 그러면 두 그룹이 있을까요? 부품 group(1)을 반환하고 (\d*)부품을 group(2)반환 (.*)합니까?

코드 조각은 내 혼란을 없애기 위해 제공되었습니다. 내가 다루는 코드가 아닙니다. 위에 제공된 코드 String.split()는 훨씬 더 쉬운 방법 으로 수행 할 수 있습니다 .

답변:


182

캡처 및 그룹화

캡처 그룹캡처 속성 이 (pattern)있는 그룹 을 만듭니다 .

자주 보거나 사용할 수있는 관련 항목은 속성 을 캡처 하지 않고 그룹(?:pattern) 을 생성하는 이므로 비 캡처 그룹이라고 합니다.

그룹은 일반적으로 패턴의 시퀀스를 반복해야 할 때 (\.\w+)+또는 ^(0*1|1*0)$( ^, then 0*1또는 1*0, then $) 대 ^0*1|1*0$( ^0*1또는 1*0$) 와 같이 대체가 적용될 위치를 지정 해야 할 때 사용됩니다 .

그룹화와는 별도로 캡처 링 그룹은 캡처 링 그룹 내부의 패턴과 일치하는 텍스트도 기록합니다 (pattern). 귀하의 예제를 사용하여 (.*):, .*일치 ABC:경기가 :있기 때문에, 그리고 .*그룹을 캡처 안에 (.*)텍스트가 ABC캡처 그룹 1에 대한 기록됩니다.

그룹 번호

전체 패턴은 그룹 번호 0으로 정의 됩니다.

패턴의 모든 캡처 그룹은 1부터 인덱싱을 시작합니다. 인덱스는 캡처 그룹의 여는 괄호 순서로 정의됩니다 . 예를 들어, 다음은 아래 패턴의 5 개 캡처 그룹 모두 입니다.

(group)(?:non-capturing-group)(g(?:ro|u)p( (nested)inside)(another)group)(?=assertion)
|     |                       |          | |      |      ||       |     |
1-----1                       |          | 4------4      |5-------5     |
                              |          3---------------3              |
                              2-----------------------------------------2

그룹 번호는 \n패턴의 역 참조 및 $n대체 문자열에 사용됩니다.

다른 정규식 버전 (PCRE, Perl)에서는 하위 루틴 호출 에도 사용할 수 있습니다 .

를 사용하여 특정 그룹과 일치하는 텍스트에 액세스 할 수 있습니다 Matcher.group(int group). 그룹 번호는 위에 명시된 규칙으로 식별 할 수 있습니다.

일부 정규식 버전 (PCRE, Perl)에는 다른 분기의 교대 그룹캡처 하는 데 동일한 번호 를 사용할 수 있는 분기 재설정 기능이 있습니다 .

그룹 이름

Java 7에서 명명 된 캡처 링 그룹을 정의하고 (?<name>pattern)와 일치하는 콘텐츠에 액세스 할 수 있습니다 Matcher.group(String name). 정규식은 더 길지만 정규식과 일치 시키거나 추출하려는 내용을 나타 내기 때문에 코드가 더 의미가 있습니다.

그룹 이름은 \k<name>패턴의 역 참조 및 ${name}대체 문자열에 사용됩니다.

명명 된 캡처 링 그룹은 여전히 ​​동일한 번호 매기기 체계로 번호가 지정되므로을 통해 액세스 할 수도 있습니다 Matcher.group(int group).

내부적으로 Java의 구현은 이름에서 그룹 번호로 매핑됩니다. 따라서 2 개의 다른 캡처 그룹에 동일한 이름을 사용할 수 없습니다.


1
와! 중첩 그룹 순서가 작동하는 방식으로 비 캡처 그룹을 설명해 주신 @nhahtdh에게 감사드립니다. 마침내 설명을 읽을 때까지 그룹 번호가 어떻게 작동하는지에 대해 어리둥절했습니다. 감사합니다!
MMeah

92

나머지 우리를 위해

이것이 어떻게 작동하는지에 대한 간단하고 명확한 예입니다.

정규식 : ([a-zA-Z0-9]+)([\s]+)([a-zA-Z ]+)([\s]+)([0-9]+)

끈: "!* UserName10 John Smith 01123 *!"

group(0): UserName10 John Smith 01123
group(1): UserName10
group(2):  
group(3): John Smith
group(4):  
group(5): 01123

보시다시피 괄호로 묶인 5 개의 그룹을 만들었습니다.

! * 및 *! 더 명확하게하기 위해 양쪽에. 이러한 문자는 RegEx에 없으므로 결과에 생성되지 않습니다. Group (0)은 일치하는 전체 문자열 (내 모든 검색 기준을 한 줄로 표시) 만 제공합니다. 검색 기준에 공백 문자가 포함되지 않았기 때문에 그룹 1은 첫 번째 공백 바로 앞에서 중지됩니다. 그룹 2와 4는 단순히 공백입니다.이 경우에는 문자 그대로 공백 문자이지만 탭이나 줄 바꿈 등이 될 수도 있습니다. 그룹 3에는 공백이 포함되어 있습니다. 검색 기준에 입력했기 때문입니다.

이것이 의미가 있기를 바랍니다.


1
초보자도 이해하기 쉬운 완벽한 예입니다. 나는 이것이 파이썬의 reg ex 그룹화와 동일하다는 것을 의심합니다. 아니면 차이가 있습니까? 나는 reg ex를 처음 사용하기 때문에 두 언어 모두에서 약간 혼란스러워합니다.
Mani

1
유효한 Java 정규식이 아닙니다. 백 슬래시는 두 배 여야합니다.
Nicolas Raoul

1
@NicolasRaoul : 이중 백 슬래시는 문자열 리터럴의 이스케이프 구문 때문입니다. 실제 정규식 구문 (예 : 정규식이 포함 된 문자열을 콘솔에 인쇄하는 경우)에는 이중 백 슬래시가 필요하지 않습니다.
nhahtdh

@NicolasRaoul 유능한 IDE를 사용하여 정규식 문자열을 실제 자바 코드에 복사하여 붙여 넣는 경우 IDE는 필요에 따라 이스케이프 슬래시의 형식을 올바르게 지정합니다. 하지만 내 Regex는 기술적으로나 구문 적으로 정확하며 정규식 코드와 얻은 결과 (매우 구체적인 예를 사용하여) 간의 연관성을 보여주는 주요 목적을 제공합니다 ... 조금 밝게 ... ☺
Michael Sims

44

괄호 ()는 정규식 구문을 그룹화하는 데 사용됩니다.

group(1)괄호 사이에있는 문자열이 포함되어 (.*)있으므로 .*이 경우를

그리고 group(0)일치하는 전체 문자열을 포함합니다.

더 많은 그룹 (읽기 (...))이 있으면 다음 인덱스 (2, 3 등)가있는 그룹에 배치됩니다.


2
그래서, 괄호를 추가하는 것이 실제로 그룹을 만드는 것입니다.
P basak 2013 년

3
예, 그렇게 말할 수 있습니다.
Michal Borek 2013 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.