2

私のツールはプレーンテキストを取得し、タグ内のテキストから用語を置き換えることによって徐々に「タグ」を生成します。いくつかの複合用語が存在するため、(私が思うに)唯一の方法はReplaceAll正規表現を使用することです。

stackoverflowの友達のおかげで、私の最後の質問で、アプリに優れた正規表現を取得しましたが、テストの結果、新しいニーズが浮かび上がりました。

「タグの外側と別の単語の外側のすべての単語を置き換える正規表現」

元のコード:

String str = "world worldwide <a href=\"world\">my world</world>underworld world";
str = str.replaceAll("\\bworld\\b(?![^<>]*+>)", "repl");
System.out.println(str);

「アンダーワールド」や「ワールドワイド」ではなく、「ワールド」(もちろんタグの外)のみを置き換える必要があります

期待される結果

repl worldwide <a href="world">my world</world>underworld repl
4

1 に答える 1

3

正規表現がこの仕事に最適なツールだとは思いませんが、現在持っているものを微調整して最適化したいだけなら、境界という単語を使用し\b、不要なキャプチャ グループとオプションの繰り返し指定子を捨てて、所有格を使用できます。繰り返し:

\bworld\b(?![^<>]*+>)

幅がゼロの単語境界アンカーで囲まれている\bworld\bことを確認します。これにより、 inと"world"が一致しなくなります。単語境界の定義は、希望どおりではない場合があることに注意してください。たとえば、 inと一致しません。"world""underworld""worldwide"\bworld\b"world""a_world_domination"

元のパターンには、 のようなサブパターンも含まれています(x+)?。これは、単純にx*. つまり?、 "one-or-more"の "zero-or-one" ではなく+、単に "zero-or-more"*です。

キャプチャ グループ(…)は機能的には不要であり、置換の置換にキャプチャは必要ないように思われるため、それを取り除くとパフォーマンスが向上します (グループ化の側面が必要で、キャプチャの側面が必要ない場合は、次のことができます)。(?:…)代わりに非キャプチャ グループを使用してください)。

[^<]の代わりに、両方のブラケットを で禁止することにも注意してください[^<>]。この場合、バックトラックが必要ないため、繰り返しを所有格として指定できるようになりました。

([…]文字クラス. のようなもの[aeiou]は、小文字の母音のいずれかに一致します。[^…]否定文字クラスです。小文字の母音以外[^aeiou]のいずれかに一致します。)

もちろん(?!…)否定的な先読みです。これは、特定のパターンが一致しないことを表明します。したがって、全体的なパターンは次のようになります。

\bworld\b(?![^<>]*+>)
\_______/\__________/ NOT the case that
 "world"                      the first bracket to its right is a closing one
 surrounded by
 word boundary anchors

参考文献


Java 文字列リテラルでバックスラッシュを取得するには、それを 2 倍にする必要があることに注意してください。したがって、Java 文字列リテラルとしてのパターン全体は"\\bworld\\b(?![^<>]*+>)".

于 2010-08-13T14:10:38.773 に答える