1. ホーム
  2. java

[解決済み] JavaでのRegex名前付きグループ

2022-04-21 07:44:44

質問

私の理解では java.regex パッケージは、名前付きグループ ( http://www.regular-expressions.info/named.html ということで、どなたかサードパーティのライブラリの紹介をしていただけませんか?

を調べました。 jregex しかし、その最後のリリースは2002年で、java5では(確かにちょっと試しただけですが)私には動きませんでした。

解決方法は?

( 更新情報 : 2011年8月 )

として ジオフレーン で言及しています。 回答 , Java 7 は名前付きグループをサポートするようになりました .

トクリスト は、コメントでサポートが限定的であることを指摘しています。

彼は という質問に対して、「そうですね。 Java Regex Helper "

Java 7 の正規表現の名前付きグループのサポートは、以下の記事で紹介されています。 2010年9月 オラクルのブログで .

Java 7の正式リリースでは、名前付きキャプチャグループをサポートするコンストラクトがあります。

  • (?<name>capturing text) で、名前付きグループ "name"を定義します。
  • \k<name> は、名前付きグループの後方参照を行います。
  • ${name} Matcherの置換文字列の中で、取り込んだグループを参照する。
  • Matcher.group(String name) は、与えられた "名前付きグループ" によって捕捉された入力の部分列を返します。

Java 7以前の他の選択肢 がありました。


( オリジナル回答 : 2009年1月 次の2つのリンクは現在壊れています。)

Regexを独自にコード化しない限り、名前付きグループを参照することはできません。

それはまさに このスレッドでGorbush2が行ったこと .

Regex2

(で再指摘されたように、限定的な実装です)。 クリスト tchristは、その制限を次のように説明しています。

<ブロッククオート

同じ名前に対して1つの名前付きグループしか持てないこと(これは必ずしもコントロールできるわけではありません!)、正規表現内の再帰処理に使用できないことです。

注:本当の意味での正規表現の再帰性はPerlやPCREの正規表現に例があり、それは以下の記事で紹介されています。 Regexpパワー , PCRE仕様 そして バランスのとれた括弧を使用した文字列のマッチング スライド)

文字列です。

"TEST 123"

RegExp:

"(?<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;
                }