Javaの正規表現の名前付きグループ


173

java.regexパッケージが名前付きグループ(http://www.regular-expressions.info/named.html)をサポートしていないことは私の理解ですので、誰かが私をサードパーティのライブラリに向けることができますか?

私はjregexを調べましたが、最後のリリースは2002年であり、java5で動作しませんでした(確かに少しだけ試してみました)。


3
あなたの理解は間違っています。JDK7は名前付きグループを処理します。
tchrist

2
@tchrist 2009年にはJDK7はありませんでした。
Alex78191 2017年

回答:


275

更新2011年8月

以下のようgeofflaneがに言及彼の答えJavaの7は現在、名前のグループをサポート
tchristはコメントの中でサポートは限定的だと指摘しています。
は彼の素晴らしい答え「Java Regex Helper」で制限について詳しく説明しています

Java 7 regexというグループサポートは、2010年9月にOracleのブログで紹介されました。

Java 7の公式リリースでは、名前付きキャプチャグループをサポートする構成は次のとおりです。

  • (?<name>capturing text) 名前付きグループ「名前」を定義する
  • \k<name> 名前付きグループ「name」を後方参照するには
  • ${name} Matcherの置換文字列でキャプチャされたグループを参照する
  • Matcher.group(String name) 指定された「名前付きグループ」によってキャプチャされた入力サブシーケンスを返します。

Java 7より前の代替手段は次のとおりです。


元の回答2009年1月、次の2つのリンクが壊れています)

Regexの独自のバージョンをコーディングしない限り、名前付きグループを参照することはできません...

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

Regex2

(ASCII識別子のみを検索するため、tchristによって再度指摘されているように、制限された実装。tchristは、次のように制限を詳しく説明します。

同じ名前(常に制御できるわけではありません)ごとに1つの名前付きグループしか持つことができず、それらを正規表現内の再帰に使用できません。

注:正規表現の再帰の例は、PerlとPCREの正規表現で見つけることができます。これについては、Regexp PowerPCREの仕様、および括弧囲まれた文字列のマッチングスライドで説明しています)

例:

ストリング:

"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識別子を探しています。それは間違っている。Javaが識別子で許可するものを探しているはずです!!
tchrist

1
あなたがとても良心的であるように見えるだけなので、限られた部分は、ASCIIとUnicodeの名前についてはそれほど重要ではありません。それらを正規表現内の再帰に使用できない。
tchrist

@tchrist:この精度(同梱)をありがとうございます。また、「Java Regexヘルパー」(賛成)のすばらしい回答へのリンクを追加しました。
VonC、2011

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内から使用できません。
桜庭

4
このプロジェクトのGitHubフォークをチェックしてください。このフォークは、元のバグをいくつか修正しています。また、Maven Centralでもホストされています。
tony19 2012

1
私の場合の注意点として、Githubのtony19フォークは0.1.8以降のAndroidでは動作しません。
チャックD

2
@ RubberMallet、Android固有の問題が修正され、0.1.9になる予定です。
tony19


2

java7より前のバージョンを実行している場合、名前付きグループはjoniOniguruma regexpライブラリのJavaポート)でサポートされています。ドキュメントはまばらですが、私たちにとってはうまく機能しています。
バイナリはMaven(http://repository.codehaus.org/org/jruby/joni/joni/)から入手できます。


私は上記のライアンが述べたjoniオプションに非常に興味があります-名前付きキャプチャグループを使用したコードスニペットはありますか-基本的なマッチングと検索を正しく機能させることができました-しかし、どの方法を使用するかわかりませんgroupNamesにアクセスするか、グループ名を使用してキャプチャの値を取得します。
malsmith

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.