Java의 정규식 명명 된 그룹


173

그것은 나의 이해입니다 java.regex패키지라는 이름의 그룹 (에 대한 지원이없는 http://www.regular-expressions.info/named.html 않는 타사 라이브러리를 향해 캔 누구 포인트 나 정도)?

jregex를 살펴 보았지만 마지막 릴리스는 2002 년이며 java5에서는 저에게 효과적이지 않았습니다 (간단히 시도했습니다).


3
이해가 잘못되었습니다. JDK7은 명명 된 그룹을 처리합니다.
— tchrist

2
@tchrist 2009 년에는 JDK7이 없었습니다.
— Alex78191

답변:


275

( 업데이트 : 2011 년 8 월 )

으로 geofflane가 에 언급 그의 대답 , 자바 7은 현재라는 이름의 그룹을 지원 .
tchrist 는 의견에서 지원이 제한적이라고 지적합니다.
그는 훌륭한 답변 " Java Regex Helper " 의 제한 사항에 대해 자세히 설명합니다.

Java 7 정규식 그룹 지원은 2010 년 9 월 Oracle 블로그에서 다시 발표되었습니다 .

Java 7의 공식 릴리스에서 명명 된 캡처 그룹을 지원하는 구성은 다음과 같습니다.

  • (?<name>capturing text) 명명 된 그룹 "name"을 정의
  • \k<name> 명명 된 그룹 "name"을 역 참조하는 방법
  • ${name} Matcher의 대체 문자열에서 캡처 된 그룹을 참조
  • Matcher.group(String name) 지정된 "명명 된 그룹"에 의해 캡처 된 입력 서브 시퀀스를 리턴합니다.

Java 7 이전의 다른 대안 은 다음과 같습니다.


( 원래 답변 : 2009 년 1 월 , 다음 두 링크가 끊어짐)

자신의 Regex 버전을 코딩하지 않으면 명명 된 그룹을 참조 할 수 없습니다.

그것이 바로이 스레드에서 Gorbush2가 한 일입니다 .

정규식 2

ASCII 식별자 만 찾기 때문에 tchrist가 다시 지적한 제한적인 구현 . tchrist는 다음과 같은 제한 사항을 자세히 설명합니다.

같은 이름마다 하나의 명명 된 그룹 만 가질 수 있으며 (항상 제어 할 수있는 것은 아닙니다!) 정규식 재귀에 사용할 수 없습니다.

참고 : Regexp Power , PCRE 사양 및 균형 괄호가있는 일치 문자열에 언급 된 것처럼 Perl 및 PCRE 정규 표현식에서 실제 정규식 재귀 예제를 찾을 수 있습니다 )

예:

끈:

"TEST 123"

정규식 :

"(?<login>\\w+) (?<id>\\d+)"

접속하다

matcher.group(1) ==> TEST
matcher.group("login") ==> TEST
matcher.name(1) ==> login

바꾸다

matcher.replaceAll("aaaaa_$1_sssss_$2____") ==> aaaaa_TEST_sssss_123____
matcher.replaceAll("aaaaa_${login}_sssss_${id}____") ==> aaaaa_TEST_sssss_123____ 

(구현에서 추출)

public final class Pattern
    implements java.io.Serializable
{
[...]
    /**
     * Parses a group and returns the head node of a set of nodes that process
     * the group. Sometimes a double return system is used where the tail is
     * returned in root.
     */
    private Node group0() {
        boolean capturingGroup = false;
        Node head = null;
        Node tail = null;
        int save = flags;
        root = null;
        int ch = next();
        if (ch == '?') {
            ch = skip();
            switch (ch) {

            case '<':   // (?<xxx)  look behind or group name
                ch = read();
                int start = cursor;
[...]
                // test forGroupName
                int startChar = ch;
                while(ASCII.isWord(ch) && ch != '>') ch=read();
                if(ch == '>'){
                    // valid group name
                    int len = cursor-start;
                    int[] newtemp = new int[2*(len) + 2];
                    //System.arraycopy(temp, start, newtemp, 0, len);
                    StringBuilder name = new StringBuilder();
                    for(int i = start; i< cursor; i++){
                        name.append((char)temp[i-1]);
                    }
                    // create Named group
                    head = createGroup(false);
                    ((GroupTail)root).name = name.toString();

                    capturingGroup = true;
                    tail = root;
                    head.next = expr(tail);
                    break;
                }

위의 두 링크가 모두 끊어진 것 같습니까?
— Jonas

이 코드는 버그가 있습니다. ASCII 식별자를 찾고 있습니다. 그건 틀렸어요. 자바가 식별자에서 허용하는 것을 찾고 있어야합니다!
— tchrist

1
참고로 당신은 너무 양심적 인 것처럼 보이기 때문에 제한된 부분은 ASCII와 유니 코드 이름에 관한 것이 아니라 같은 이름 당 하나의 명명 된 그룹 만 가질 수 있기 때문입니다 (항상 제어 할 수있는 것은 아닙니다!) 정규식 재귀에 사용할 수 없습니다.
— tchrist

@ tchrist :이 정밀도 (포함)에 감사드립니다. 또한 "Java Regex helper"에 대한 귀하의 훌륭한 답변에 대한 링크를 추가했습니다.
— VonC

Java의 Matcher 객체에 대한 matcher.name (int index) 메소드가 없습니다 ??
— ot0


27

그렇습니다.하지만 태양 클래스를 해킹하는 것은 지저분합니다. 더 간단한 방법이 있습니다.

http://code.google.com/p/named-regexp/

named-regexp는 표준 JDK 정규 표현식 구현을위한 씬 래퍼이며 .net 스타일에서 명명 된 캡처 그룹을 처리하는 단일 목적은 (? ...)입니다.

Java 5 및 6과 함께 사용할 수 있습니다 (일반이 사용됨).

Java 7은 명명 된 캡처 그룹을 처리하므로이 프로젝트는 지속되지 않습니다.


1
GWT 내에서 이것을 사용할 수 없습니다.
— Sakuraba

4
이 프로젝트 의 GitHub 포크 를 확인하십시오. 이 프로젝트는 원래 버그를 수정했습니다. Maven Central에서도 호스팅됩니다.
— tony19

1
필자의 경우 Github의 tony19 포크는 0.1.8부터 Android에서 작동하지 않습니다.
— 척 D

2
@RubberMallet, Android 관련 문제가 수정 되어 0.1.9에 있습니다.
— tony19


2

java7 이전 버전을 실행하는 사용자의 경우 이름 지정된 그룹은 joni ( Oniguruma regexp 라이브러리 의 Java 포트)에서 지원됩니다 . 문서는 드물지만 우리에게는 잘 작동했습니다.
바이너리는 Maven ( http://repository.codehaus.org/org/jruby/joni/joni/ )을 통해 사용할 수 있습니다 .


위의 Ryan이 언급 한 joni 옵션에 매우 관심이 있습니다. 이름이 지정된 캡처 그룹을 사용하는 코드 스 니펫이 있습니까? 기본 일치 및 검색이 올바르게 작동하지만 어떤 방법을 사용할지 알 수 없습니다. groupName에 액세스하거나 그룹 이름을 사용하여 캡처 값을 가져옵니다.
— malsmith

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.