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.