1

以下のコードを使用して、提供したテキストからさまざまなセクションを抽出しようとしました。

数字を選択し、[中括弧または"引用符で囲まれたセクションをグループに入れる必要があります。これがコードです。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Launcher2 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        PrintRegexes("100.000[$₮-45]");
    }
    public static void PrintRegexes(String textToMatch){
        Pattern p = Pattern.compile("(\\[.*?\\]|\".*?\")?.*?(\\d{1,3}(?:,\\d{3})*?(?:\\.\\d+)?).*?(\\[.*?\\]|\".*?\")",Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
        Matcher m = p.matcher(textToMatch);
        if (m.find())
        {
            for(int groups =0;groups<m.groupCount();groups++){
                System.out.println("Group "+groups+" contains "+m.group(groups));
            }
            for(int groups =0;m.find(groups);groups++){ //this will error, but right now, it's the least of my concerns
                System.out.println("Group "+groups+" contains "+m.group(groups));
            }
        }

    }
}

Group 0 contains 100.000[$₮-45]
Group 1 contains null
Group 2 contains 100.000
Group 3 contains [$₮-45]
Group 0 contains 100.000[$₮-45]
Group 1 contains null
Group 2 contains 0.000
Group 3 contains [$₮-45]
Exception in thread "main" java.lang.IndexOutOfBoundsException: No group 4 //don't care about this, I've got bigger strings(fish) to regex(fry) at the moment!
    at java.util.regex.Matcher.group(Unknown Source)
    at Launcher2.PrintRegexes(Launcher2.java:21)
    at Launcher2.main(Launcher2.java:10)

すべてのグループは同じですがgroup 2、1 つは として出力され0.000、もう 1 つは として出力され100.000ます。

どうしてこれなの?

この動作は、数字の前と後ろに何かがあると消えます。

何かを前に置くと、次の出力が得られます。

Group 0 contains [$₮-45]100.000
Group 1 contains [$₮-45]
Group 2 contains 100.000
Group 3 contains null
Group 0 contains [$₮-45]100.000
Group 1 contains null
Group 2 contains 45
Group 3 contains null

さらに奇妙な!(私にとって) 最も奇妙な点は、これが www.debuggex.com で機能することです。

パターンを間違って書いていますか?それとも、このメソッドMatcher m = p.matcher(textToMatch);がそれを構築するときにマッチャーがグループを解決せず、それが動作に影響を与えるということですか?

4

2 に答える 2

1

ここには 2 つの問題があります。

まず、m.find()グループを引数として複数回呼び出しますが、これはあなたが思っているようには機能しません。find(int start)
のJavaDoc を見ると、マッチャーがリセットされ、入力の指定された文字から検索が再開されることがわかります。これにより、後の反復で一致する短い数列が説明されます。

groups <= m.groupCount()次に、すべてのグループを取得する までループする必要があります。

    Pattern p =
            Pattern.compile("(\\[.*?\\]|\".*?\")?.*?(\\d{1,3}(?:,\\d{3})*?(?:\\.\\d+)?).*?(\\[.*?\\]|\".*?\")",
                Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
    Matcher m = p.matcher(textToMatch);
    if (m.find()) {
        for (int groups = 0; groups <= m.groupCount(); groups++) {
            System.out.println("Group " + groups + " contains " + m.group(groups));
        }
    }

版画

グループ 0 には 100.000[$₮-45]
が含まれます グループ 1 には null が含まれます
グループ 2 には 100.000 が含まれます
グループ 3 には [$₮-45] が含まれます

于 2013-04-11T13:04:38.813 に答える
0

問題はこの部分にあるようです:(?:,\\d{3})*?

私はあなたが必要だと思います((?:,\\d{3})*)?

于 2013-04-11T13:17:35.927 に答える