web-dev-qa-db-ja.com

正規表現:InCombiningDiacriticalMarksとは何ですか?

次のコードは、アクセント付き文字をプレーンテキストに変換することでよく知られています。

Normalizer.normalize(text, Normalizer.Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+", "");

「手作り」の方法をこれに置き換えましたが、replaceAllの「正規表現」の部分を理解する必要があります

1)「InCombiningDiacriticalMarks」とは何ですか?
2)文書はどこにありますか? (および類似物?)

ありがとう。

79
marcolopes

\p{InCombiningDiacriticalMarks}はUnicodeブロックプロパティです。 JDK7では、2部表記\p{Block=CombiningDiacriticalMarks}を使用して記述できます。これは読者にとってわかりやすい場合があります。文書化されています ここUAX#44:「Unicode文字データベース」

つまり、コードポイントは、特定の範囲(ブロック)内にあり、その名前で物事に使用するために割り当てられています。これは悪いアプローチです。なぜなら、その範囲のコードポイントが特定のものであるかどうか、またそのブロックの外側のコードポイントが本質的に同じ文字ではないという保証はないからです。

たとえば、\p{Latin_1_Supplement}ブロックには、é、U + 00E9などのラテン文字があります。しかし、そこにはnotラテン文字もあります。そしてもちろん、あちこちにラテン文字もあります。

ブロックはあなたが望むものではありません。

この場合、プロパティ\p{Mn}、別名\p{Nonspacing_Mark}を使用する必要があると思われます。 Combining_Diacriticalsブロック内のすべてのコードポイントは、そのようなものです。また、そのブロックにはnotである1087 Nonspacing_Marksもあります(Unicode 6.0.0以降)。

これは、\p{Bidi_Class=Nonspacing_Mark}のチェックとほとんど同じですが、完全ではありません。そのグループには、囲みマーク\p{Me}も含まれているためです。両方が必要な場合は、General [Category]プロパティへのアクセスのみを提供するため、デフォルトのJava正規表現エンジンを使用している場合、[\p{Mn}\p{Me}]と言うことができます。

JNIを使​​用して、ICU C++正規表現ライブラリを取得するために、Googleが\p{BC=NSM}のようなものにアクセスするには、ICUおよびPerlのみを使用する必要があります。 all Unicodeプロパティへのアクセスを許可します。通常のJava正規表現ライブラリは、標準のUnicodeプロパティをいくつかしかサポートしていません。 JDK7ではwill Unicodeスクリプトプロパティのサポートがありますが、これはBlockプロパティよりもほぼ無限に望ましいものです。したがって、JDK7で\p{Script=Latin}または\p{SC=Latin}、またはショートカット\p{Latin}を記述して、ラテン文字から任意の文字を取得できます。これは、very一般的に必要な[\p{Latin}\p{Common}\p{Inherited}]につながります。

すべてのキャラクターから「アクセント」マークと思われるものが削除されないことに注意してください!多くの場合、これを行うことはできません。たとえば、Đ[〜#〜] d [〜#〜]またはøからoへ。そのためには、Unicode照合テーブルの同じ主要照合強度に一致するものにコードポイントを減らす必要があります。

\p{Mn}が失敗する別の場所は、もちろん\p{Me}のようなマークを囲むことですが、もちろんマークではない\p{Diacritic}文字もあります。残念なことに、そのための完全なプロパティサポートが必要です。つまり、JNIがICUまたはPerlのいずれかを意味します。 Javaには、Unicodeサポートに関する多くの問題があります。

ああ、待って、あなたはポルトガル人だ。ポルトガル語のテキストのみを扱っている場合は、まったく問題はないはずです。

ただし、実際にはアクセントを削除したくないのではなく、「アクセントを区別せずに」一致させる必要がありますよね?その場合、 ICU4J(Java用ICU)照合クラス を使用して行うことができます。一次強度で比較すると、アクセント記号はカウントされません。私はスペイン語のテキストを頻繁に処理するため、これを常に行います。あなたがそれを必要とするならどこかに座っているスペイン人のためにこれをする方法の例があります。

68
tchrist

しばらくかかったが、私はそれらをすべて釣った:

正規表現はこちら これには、「通常」の範囲でバイパスされるものを含むすべてのzalgo文字が含まれます。

([\u0300–\u036F\u1AB0–\u1AFF\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F\u0483-\u0486\u05C7\u0610-\u061A\u0656-\u065F\u0670\u06D6-\u06ED\u0711\u0730-\u073F\u0743-\u074A\u0F18-\u0F19\u0F35\u0F37\u0F72-\u0F73\u0F7A-\u0F81\u0F84\u0e00-\u0eff\uFC5E-\uFC62])

これで時間を節約できることを願っています。

4