フォーラム

Mac Java:文字列replaceAllメソッドを使用すると、無限ループが発生しますか?

モデレーター名誉
オリジナルポスター
2004年9月2日
センテニアル州
  • 2007年12月7日
文字列を処理し、SRC属性のパス(HTMLから)を新しいパスに置き換えるコードがあります。ただし、特定の属性値を使用すると、replaceAllメソッドは、単に一致しない(または一致する)のではなく、無限ループに入るように見えます。次のJavaを実行すると、modifiedStringの出力を取得するのではなく、ハングしているように見えます。これはJavaのreplaceAllメソッドの正当なバグですか、それとも何か間違ったことをしていますか?

コード:class ReplaceAllBugApp { public static void main(String[] args) { String originalString = new String('

robbieduncan

Moderator emeritus
Jul 24, 2002


Harrogate
  • Dec 7, 2007
I'd not be surprised if it could end up in an infinite loop if the string you replace ends up inserting the string you are replacing...

dejo

Moderator emeritus
Original poster
Sep 2, 2004
The Centennial State
  • Dec 7, 2007
robbieduncan said: I'd not be surprised if it could end up in an infinite loop if the string you replace ends up inserting the string you are replacing...
But the strings are definitely different in this example case. We're going from src='/images/subdir/company_logo_final.jpg'js-selectToQuoteEnd'>

jeremy.king

Jul 23, 2002
Holly Springs, NC
  • Dec 7, 2007
Are you simply looking to replace the path on the images?

dejo

Moderator emeritus
Original poster
Sep 2, 2004
The Centennial State
  • Dec 7, 2007
kingjr3 said: Are you simply looking to replace the path on the images?
Yes.

kylos

Nov 8, 2002
MI
  • Dec 7, 2007
dejo said: But the strings are definitely different in this example case. We're going from src='/images/subdir/company_logo_final.jpg'bbCodeBlock-expandLink js-expandLink'>

Run it through a debugger and see where it hangs. I'd recommend Eclipse, as the version I'm using has the source for java.util.regex (used by String.replaceAll()), so you can step through the code and possibly see the actual problem.

robbieduncan said: I'd not be surprised if it could end up in an infinite loop if the string you replace ends up inserting the string you are replacing...

From Matcher.replaceAll (used by String.replaceAll()):
This method first resets this matcher. It then scans the input sequence looking for matches of the pattern. Characters that are not part of any match are appended directly to the result string; each match is replaced in the result by the replacement string. The replacement string may contain references to captured subsequences as in the appendReplacement method.

This para seems to indicate a sequential match, not a recursive one, so there should be no issues with rematching an already matched tag.

jeremy.king

Jul 23, 2002
Holly Springs, NC
  • Dec 7, 2007
dejo said: Yes.

Does this help at all?

Code:
String modifiedString = originalString.replaceAll('(?i)src ?= ?'(/?[^/]+/)*([^']+')', 'src='/webapp/UserFiles/Images/$2'); 
正規表現(つまり、一部の文字を除くすべて)を使用する場合、私は負の論理アプローチにアプローチする傾向があります

私の限られたテストケースでうまくテストされました...

正規表現がすべて奇妙になるのは、テストケースにその終了引用符がない場合、画像タグの終了スラッシュをマッチャーに公開すると、どういうわけか爆撃されると思います。そのテストプログラムをバグとしてsunに提出することをお勧めします。

モデレーター名誉
オリジナルポスター
2004年9月2日
センテニアル州
  • 2007年12月7日
kingjr3は言った:これはまったく役に立ちますか?

コード:String modifiedString = originalString.replaceAll('(?i)src ?= ?'(/?[^/]+/)*([^']+')', 'src='/webapp/UserFiles/Images/$2');
正規表現(つまり、一部の文字を除くすべて)を使用する場合、私は負の論理アプローチにアプローチする傾向があります

私の限られたテストケースでうまくテストされました...

正規表現がすべて奇妙になるのは、テストケースにその終了引用符がない場合、画像タグの終了スラッシュをマッチャーに公開すると、どういうわけか爆撃されると思います。そのテストプログラムをバグとしてsunに提出することをお勧めします。
ありがとう、kingjr3、それはそれをするべきです!私はあなたのアドバイスに耳を傾け、他の正規表現のいくつかを再検討し、ネガティブロジックアプローチでやり直すことができるかどうかを確認すると思います。そして、これをバグとしてSunに提出します。私はそれが最高の正規表現ではないことを知っていますが、決してハングするべきではありません。正規表現を台無しにすると、一致しないと思います。

P.S.次に、正規表現を調整して、閉じている二重引用符がsrc =値の唯一の許可された区切り文字であるだけでなく、空白も使用できるようにします。そうすれば、src = '...'またはsrc = ...(またはsrc = '...またはsrc = ...')のいずれかに対して置換が発生します。

P.P.S.これはどのように見えますか?
コード:String modifiedString = originalString.replaceAll('(?i)src ?= ?'?(/?[^/]+/)*([^\s|']+)'?\s', 'src='/webapp/UserFiles/Images/$2' ');このようにして、新しいsrc値を強制的に 'sで囲みます。

2002年11月8日
自分
  • 2007年12月7日
デジョは言った:PS次に、正規表現を調整して、閉じている二重引用符がsrc =値の唯一の許可された区切り文字であるだけでなく、空白も使用できるようにします。そうすれば、src = '...'またはsrc = ...(またはsrc = '...またはsrc = ...')のいずれかに対して置換が発生します。

P.P.S.これはどのように見えますか?

あなたのサイトがまだ引用符を嗅ぎつけていない場合には、それはよりうまくいくでしょう。技術的には、無効な入力を受け入れますが、そのような入力を有効にするので、問題はありません。

モデレーター名誉
オリジナルポスター
2004年9月2日
センテニアル州
  • 2007年12月10日
Re:提案されたソリューション

kingjr3は言った:コード:String modifiedString = originalString.replaceAll('(?i)src ?= ?'(/?[^/]+/)*([^']+')', 'src='/webapp/UserFiles/Images/$2');
したがって、この正規表現をはるかに大きなHTML文字列(220K)に適用しようとすると、スタックオーバーフローの例外が発生するようです。考え?

2002年11月8日
自分
  • 2007年12月10日
dejo氏:つまり、この正規表現をはるかに大きなHTML文字列(220K)に適用しようとすると、スタックオーバーフローの例外が発生するようです。考え?

それははるかに小さなファイルで機能しますか?複数のsrc属性を持っているが、サイズが1kしかないものはありますか?私が尋ねる理由は、正規表現で貪欲な演算子を使用しているためです。この演算子は、ファイル全体を読み取り、許容可能な一致が見つかるまで元に戻します。正規表現エンジンの実装によっては、これにより大量のデータがスタックにプッシュされる可能性があります。

チェックしてください 数量詞に関するSunチュートリアル 詳細については。

以下の使用をお勧めします

コード:'(?i)src ?= ?'(/?[^/]+?/)*?([^']+?')'
それ以外の

コード:'(?i)src ?= ?'(/?[^/]+/)*([^']+')'
(+、*)演算子に続く疑問符は、それらを不本意な演算子に変えます。つまり、最大の文字列から開始して有効な一致になると停止するのではなく、可能な限り最小の一致で開始し、失敗するまで増加します。

jeremy.king

2002年7月23日
ノースカロライナ州ホリースプリングス
  • 2007年12月10日
大きなファイルはいつでも小さくすることができます。 NS

SC68Cal

2006年2月23日
  • 2007年12月10日
dejo氏:つまり、この正規表現をはるかに大きなHTML文字列(220K)に適用しようとすると、スタックオーバーフローの例外が発生するようです。考え?

Javaの制限へようこそ。 VMが小さすぎてタスクを処理できない可能性があります。もう少しメモリを割り当てます。

2002年11月8日
自分
  • 2007年12月10日
SC68Calは次のように述べています。Javaの制限へようこそ。 VMが小さすぎてタスクを処理できない可能性があります。もう少しメモリを割り当てます。

VMオプション-Xssを使用してVMスタックを増やしている間 五月 この状況でスタックオーバーフローを回避するのに役立ちます。スタックオーバーフローはファイルサイズに間接的にのみ関連します。オブジェクトへのローカル参照はスタックに保存されますが、実際のオブジェクトはヒープに保存されます。つまり、ファイルに関連付けられている文字列データはスタックに保存されないため、ファイルサイズによってスタックオーバーフローが直接発​​生することはありません。

Javaでは、メソッド呼び出し、プリミティブ型、および参照のみがスタックに格納されます。したがって、Javaでは、スタックオーバーフローは、深い再帰によってのみ引き起こされる可能性があります。データのごく一部のみが一致する場合に大きなファイルで貪欲な数量詞を使用すると、大量のバックトラックが発生します。 多くの 処理に時間がかかりますが、次の理由でスタックオーバーフローが発生する可能性もあります どうやら 正規表現エンジンの深い再帰。

Javaメモリに関する詳細情報 構造

OPがスタックトレースを投稿して、オーバーフローの原因を確認するのは興味深いことです。

それまでの間、気が進まない数量詞を使用すると、実行が劇的に高速化されるだけでなく、スタックの問題も解消されると思います。

jeremy.king

2002年7月23日
ノースカロライナ州ホリースプリングス
  • 2007年12月10日
カイル?言った:OPがオーバーフローの原因を確認するためにスタックトレースを投稿するのは興味深いことです。

それまでの間、気が進まない数量詞を使用すると、実行が劇的に高速化されるだけでなく、スタックの問題も解消されると思います。

Pattern.matchesまたはMatcher.matchesにお金をかけます!

過度に野心的な正規表現は、Pattern / Matcherクラスの再帰的な性質のため、ほとんどの場合、スタックオーバーフローを引き起こします。

気が進まない数量詞を試したり、行末ターミネーターを含むようにパターンを変更したり、ファイルを1行ずつ(またはタグごとに)読み取ってそれに応じてパターンを適用したりするのは不合理ではないと思います...

この猫の皮を剥ぐいくつかの方法

2002年11月8日
自分
  • 2007年12月10日
kingjr3は言った:この猫の皮を剥ぐいくつかの方法

同意しました。