2009-05-11 13 views
5

&をHTMLエンティティの一部ではない文字列に置き換える必要があります。文字列 "この& entitesは> & <" 返すよう正規表現の最適化 - Javaでアンパサンドをエスケープする

そして私は、この正規表現パターンを作ってみた "> & <この& entites": "& [-ZA-Z0-9] {2 、7}; "うまく動作します。 しかし、私は正規表現にあまり熟練していないので、100k回以上の速度をテストすると、正規表現を使わなかった以前の使用されていた方法より2倍の時間がかかります。 (しかし、いずれも100%働いていませんでした)。

Testcode:

long time = System.currentTimeMillis(); 
String reg = "&(?!&#?[a-zA-Z0-9]{2,7};)"; 
String s="a regex test 1 & 2 1&2 and &_gt; - &_lt;" 
for (int i = 0; i < 100000; i++) {test=s.replaceAll(reg, "&amp;");} 
System.out.println("Finished in:" + (System.currentTimeMillis() - time) + " milliseconds"); 

そこで問題は、最適化のいくつかの明白な方法は、それがより効果的にするために、この正規表現式があるかどうかだろうか?

+0

私のようなアンダースコアで&_gt;をentitesを書かなければならなかったか、そうでなければ、コードがためだったのシンボルとして表示したいです。 – Duveit

+0

ほとんど4人がテキストを編集して、アンパサンドをコード形式の引用符で囲みようとしました。必要なテキストを選択してコードを使用するだけで、アンパサンドは保持されます。 – cgp

答えて

6

s.replaceAll(reg, "&amp;")は毎回正規表現をコンパイルしています。パターンを一度コンパイルするとパフォーマンスがいくらか向上します(この場合は〜30%)。

long time = System.currentTimeMillis(); 
String reg = "&(?!&#?[a-zA-Z0-9]{2,7};)"; 
Pattern p = Pattern.compile(reg); 
String s="a regex test 1 & 2 1&2 and &_gt; - &_lt;"; 
for (int i = 0; i < 100000; i++) { 
    String test = p.matcher(s).replaceAll("&amp;"); 
} 
System.out.println("Finished in:" + 
      (System.currentTimeMillis() - time) + " milliseconds"); 
+0

それは本当です、それは550msから450msにダウンしました。プリコンパイルされたパターンを実装できるかどうかがわかります。 – Duveit

0

私はJavaの正規表現のクラスに詳しくはありませんが、一般的にはゼロ幅の先読みを調べることをお勧めします。アンパサンドの後。これを行うための別の方法は、正規表現で頭を吹いwihtout

Here is a link記述正と負の先読み

+0

これは私が実際にこれを作ったときに見てきたページです:肯定対否定の先読みを見ましたが、私が試みた変更は効率を上げませんでした。 – Duveit

1

Commons LangからStringEscapeUtilsを使用することです。

+0

このライブラリの一部を使用していますが、ここではアンパサンドのみを修正する必要があります。そしてそれはエンティティとシンプルなものの組み合わせかもしれない文字列を受け入れなければなりません。 - ありがとう。 – Duveit

2

ルックアヘッドアサーションから&を除外する必要があります。

&(?!#?[a-zA-Z0-9]{2,7};) 

のか正確には:だから、この正規表現を試してみてください

&(?!(?:#(?:[xX][0-9a-fA-F]|[0-9]+)|[a-zA-Z]+);)