1

Javaプログラムでは、これらのサブ文字列の特定の文字列内のすべての出現箇所を調べたいと思います:$$、または$ \ d(記号「$」の後に整数が続く)。

私の問題は、一致した文字列が特定の文字シーケンスによって制限された部分文字列の一部ではない場合にのみ一致が発生するという制約を追加したときに始まりました。

たとえば、「/{」と「/}」で囲まれた部分文字列の一部である場合、一致を無視したいと思います。

次の例では、$$または$ \ dがすべて出現しますが、「/{」および「/}」内にある場合は一致を無視するという追加の制約は考慮されていません。

public static final String PARAMETERS_PREFIX = "$";
public static final String ALL_PARAMS_SUFFIX = "$";
public static final String BEGIN_JAVA_EXPRESSION = "/{";
public static final String END_JAVA_EXPRESSION = "/}";
...
String test = "$1 xxx $$ " //$1 and $$ are matches
  + BEGIN_JAVA_EXPRESSION + "xxx $2 xxx" + END_JAVA_EXPRESSION; //$2 SHOULD NOT be a match
Set<String> symbolsSet = new LinkedHashSet<String>();
Pattern pattern = Pattern.compile(Pattern.quote(PARAMETERS_PREFIX)+"(\\d+|"+Pattern.quote(ALL_PARAMS_SUFFIX)+")");
Matcher findingMatcher = pattern.matcher(test);
while(findingMatcher.find()) {
  String match = findingMatcher.group();
  symbolsSet.add(match);
}
return new ArrayList<String>(symbolsSet);

特定の部分文字列の一部ではないキーワードを見つけることに加えて、後でそれらのキーワードのみを特定の値に置き換えることができるようにしたいと思います。次に、一致する前に区切られた文字の間のすべてを削除するオプションはおそらく役に立ちません。後で、一致したトークンが特定の値に置き換えられた元の文字列を取得できるようにする必要があり、区切られた領域内のトークンは変更せずに残します。適切な正規表現が見つかった場合、これは簡単なはずです。

誰かがこの問題の正しい正規表現を書く方法についてのヒントを教えてもらえますか?

4

5 に答える 5

2

複数の正規表現を使用することは許可されていますか?あまりセクシーではないかもしれませんが、3つの正規表現を使用すると非常に簡単にこれを行うことができます。(これらは実際の正規表現ではありません)1。探している文字列を取得するため($$ | $ {num})2.'/{'の場合3.'/}'の場合

2と3の無効な領域を一致させるのはかなり簡単なはずです。次に、これらのスパンを使用して、1の結果を削除できます。

于 2012-05-02T19:17:15.367 に答える
1

これには複数の正規表現を使用することをお勧めします。一度にすべてを実行しようとすると、魅力的ではありますが、かなり厄介なようです。

  1. 文字列から「Java式」を削除します。/{.*?/}
  2. 結果の文字列でマッチャーを実行します。\$(?:\d+)?

注:私は最初の式に怠惰だったので、すべての発生の/{後に、最終的には/}ネストが発生するかどうかが想定されます。

于 2012-05-02T19:26:35.273 に答える
1

必要な最初の部分は、この正規表現を使用して実現できます。

(?<!/{)\($[$|\d])(?!}/)

したがって、これを実行した後、グループ内のすべての一致を取得します。これからは、グループ内の一致を評価し、適切な置換を見つけることによって、Javaにハードワークを実行させることができます。

どういうわけか後方参照を使用して置換ビットを実行できるはずですが、それは理解できると思います。

アップデート:

(?<!/{)-それはネガティブな後ろ姿です-それは言います:現在の位置から、前の文字はではないと断言し/{ます。これがtrueと評価された場合、/ {の一致は破棄され、実際の一致が開始されます。先読み/後読みは、試合に参加しないゼロ幅のアサーションです。

(?!}/)-同様ですが、反対方向です-現在の位置から、次の文字は}/ではないと主張します。これらも試合に参加しません。したがって、これらの条件が満たされた場合でも、一致はアサーション内のテキスト、つまり$$または$\dになります。

ところで:いくつかの文字をエスケープする必要がある可能性があります-私が覚えているのは{と$文字クラス外です

(?<!/\{)\(\$[$|\d])(?!}/)

参照: Javaで正規表現のためにテキストをエスケープする方法

于 2012-05-02T20:20:44.160 に答える
0

1つの正規表現でそれができるかどうかはわかりません。誰もこの究極の正規表現を提供できない場合、私は少し回避策を作成しました:

public static final String PARAMETERS_PREFIX = "$";
public static final String ALL_PARAMS_SUFFIX = "$";
public static final String BEGIN_JAVA_EXPRESSION = "/{";
public static final String END_JAVA_EXPRESSION = "/}";

    String test = "$1 xxx $$ " //$1 and $$ are matches
    + BEGIN_JAVA_EXPRESSION + "xxx $2 xxx" + END_JAVA_EXPRESSION; //$2 SHOULD NOT be a match
    Set<String> symbolsSet = new LinkedHashSet<String>();
    Pattern pattern = Pattern.compile(Pattern.quote(PARAMETERS_PREFIX)+"(\\d+|"+Pattern.quote(ALL_PARAMS_SUFFIX)+")");
    Matcher findingMatcher = pattern.matcher(test);
    while(findingMatcher.find()) {
        String match = findingMatcher.group(0);
        int idx= findingMatcher.start();
        int bexIdx = test.lastIndexOf(BEGIN_JAVA_EXPRESSION,idx);
        if(bexIdx!=-1){
            int endIdx = test.indexOf(END_JAVA_EXPRESSION,bexIdx);
            if(endIdx<idx){
                symbolsSet.add(match);
            }
        }
        else{
            symbolsSet.add(match);
        }
    }
于 2012-05-02T20:09:57.070 に答える
0

ルックアラウンドでパターンを使用できます:

(?<!\\{[^\\}]{0,100})\\$(\\d|\\$)(?![^\\{]*\\})

  • (?<!\\{[^\\}]{0,100})先行値を制限するために使用されるグループ

    これはネガティブルックビハインドを使用します:{?<!X}、ここXで、はメイン式の前に置くことができない正規表現です。Javaでは、明らかな最大長がないと負のlokbehindを使用できず、その場合はを使用できません\\{.*Integer.MAX_VALUE、ouを使用できますtestString.length()。もう1つ、開始記号の前に終了記号が見つかったかどうかを確認する必要があります。したがって、式は[^\\}]の代わりになり.ます。

  • \\$(\\d|\\$)メイングループが求めた

    通常ここに。

  • (?![^\\{]*\\})事後値を制限するために使用されるグループ

    これは負の先読みを使用します:{?!X}、ここXで、はメイン式を引き継ぐことができない正規表現です。ここでは、固定長を使用できます。ここでも、部分文字列の開始記号が見つかったかどうかを確認する必要があります。次に、[^\\{]*の代わりにを使用します.*

ただし、制約を追加すると、正規表現がさらに複雑になります。


パターンをテストするための文字列:"$1 xx3x $$ /{xxx $2 xxx/} $4"

于 2012-05-02T20:32:44.337 に答える