2

私は基本的な正規表現でかなり大丈夫です。しかし、千の分離を大量に行うために使用されるこのコード行は、私の知識を超えており、それをかなりグーグルで検索しても、私の好奇心を満足させることはできませんでした。次のコード行を説明してください。

someString.replaceAll("(\\G-?\\d{1,3})(?=(?:\\d{3})++(?!\\d))", "$1,");

私は特に正規表現の構造を理解していません"(?=(?:\d{3})++(?!\d))"

よろしくお願いします。

4

3 に答える 3

3

"(?=(?:\d{3})++(?!\d))"先読みアサーションです。

これは、「((キャプチャする必要のない3桁の数字)が1回以上繰り返される(そしてもう一度1回以上繰り返される)(数字が続かない))が続く場合にのみ一致することを意味します。表記については、この説明(?:...)を参照してください。これは非キャプチャグループと呼ばれ、試合後にこのグループを参照する必要がないことを意味します。

"(\\G-?\\d{1,3})"は実際に一致する必要がある部分です(ただし、上記の条件が満たされている場合のみ)。

編集:私+は特殊文字でなければならないと思います、そうでなければそれはただプラスです。それが特殊文字である場合(そしてクイック検索でJavaでもあることが示唆される場合)、2番目の文字は冗長です。

編集2:アラン・ムーアのおかげで、それは今や明らかです。2つ目+は所有格の一致を意味します。つまり、できるだけ多くの3桁のグループをチェックした後、それらの後に非数字が続かないことが見つからない場合、エンジンは3をステップする代わりにすぐに諦めます。数字グループバック。

于 2012-04-07T16:08:47.773 に答える
3

この式には、いくつかの高度な機能が含まれています。まず、最も簡単:\d{3}正確に3桁を意味します。これらはあなたの数千です。

次に:++これは+(1つ以上を意味する)の変形ですが、所有格、つまり何千ものすべてを食べることを意味します。なぜこれが必要なのか完全にはわかりません。

?:これは、キャプチャされていないグループであることを意味します。これは、パフォーマンス上の理由から存在するものであり、省略できると思います。

?=これは、そのグループが存在するかどうかだけがチェックされ、一致した文字列にはカウントされないことを意味すると思います。つまり、置き換えられません。

?!は否定的な先読みです-私はそれを完全には理解していませんが、それは一致してはならないことを意味すると思います。つまり、一致したシーケンスの最後に別の数字がないことを意味します。これにより、最初のグループが正しい数字を取得できるようになります。たとえば、10000は10(000)としてのみ一致させることができますが、私が何を意味するかがわかる場合は1(000)0として一致させることはできません。

先読みを通して、私がそれを正しく理解している場合(私はそれをテストしていません)、最初のグループだけが実際に置き換えられます。これは一致するグループだからです。

于 2012-04-07T16:21:36.337 に答える
2

私にとって、その正規表現の最も興味深い部分はです\G。小数部にコンマがあればそれを追加しないようにするために、それが何のためにあるのかを思い出すのに少し時間がかかりました。正規表現が単純な場合:

(-?\d{1,3})(?=(?:\d{3})++(?!\d))

...この番号:

12345.67890

...最終的には次のようになります:

12,345.67,890

ただし、先頭に追加\Gすると、試合は文字列の先頭または前の試合が終了した位置でのみ開始できます。したがって、次345の理由で一致しません。また、文字列の一部をスキップする必要があるため、一致しません。そしてそれは正しく戻ります:.67

12,345.67890

これは質問に対する答えではないことは知っていますが、言及する価値があると思いました。

于 2012-04-07T19:46:14.007 に答える