2017-02-07 5 views
3

私の問題は、UTF-8を含むデータファイルがあることです。そのほとんどは有効であり、保管する必要がありますが、そのうちのいくつかはランダムな "ゴミ" UTF-8、すなわち0xf0 - 0xffの範囲内にあります。不良データ用の六角の例は、私が検索し、最初のバイトが範囲0xf0 - 0xffにある文字に置き換えますperlスクリプトを記述しようとしているファイルからUTF-8文字の範囲を取り除くスクリプト

f4 80 80 ab f4 80 80 b6 f4 80 80 
a5 f4 80 80 a6 f4 80 80 83 f4 80 80 b6 f4 80 81 
84 f4 80 81 98 f4 80 81 87 f4 80 81 8c f4 

下に見ることができます。 this websiteにコードページはプライベート使用としてリストされています。

私の既存の試みは、のようなperl -CSD -pi.orig -e 's/[\x{f4}-\x{ff}]/?/g'は、私はPerlの専門家の多くはないよperlのv5.12.5

を実行すると、何もしない、または唯一のマルチバイト文字の最初のバイトを削除することができたのいずれかutf-8の専門家もいません。私はruby/python/C++(98)/ Linuxでこれが比較的移植性の高いものであればこれを行うこともできます。

ここには、ガベージデータのスニペットへのリンクがあります。 http://pastebin.com/LR0StPHu

+0

私の質問には、デモデータを自分のコードにどうやって入れるのですか? :D – simbabque

+0

@simbabque Pastbin for you http://pastebin.com/LR0StPHu –

答えて

5

[OK]をいくつか混在しないでください。

最初のバイトが0xf0であるUTF-8文字は4バイト長です。正式なUnicode文字をエンコードするのに最も必要なものです。可能なUnicode範囲の94%以上が4番目のバイト0xf0が単一コードページにはマッピングされず、私的使用領域にはマッピングされないことが必要なためです。

このような文字は、Basic Multilingual Planeの外側のです。しかし、これは無効または私的使用とは異なります。コードポイントがU + FFFF(10進値65,535)よりも大きいことを意味します。

あなたはBMP外のすべての文字を除外したい場合は、この正規表現に一致するものを検索する必要があります。

[\x{10000}-\x{10FFFF}] 

その進コードで文字を含めるように... }補間構文をPerlの\x{を使用していますポイント値。あなたが実際にPerlを使用しているなら、使いやすさのために、正規表現を変数に入れたいかもしれません(引用符正規表現の構造qr( ... )、裸のスラッシュは代入時に正規表現とすぐに一致するようにしようとします)時間):

my $not_bmp = qr([\x{10000}-\x{10FFFF}]); 

しかし、再び、その正規表現にマッチする文字を削除することは可能のUnicode文字の94%以上を除去し、そのために何をしたいのです確認してください。

BMPの中にある専用の文字を除外したい場合は、その範囲を特に除外します。 PerlやPythonや他のUTF-8対応言語では、バイトを心配する必要はありません。コードポイントをチェックするだけです。 Wikipediaとして

は3つのプライベート使用領域がこれらのコード・ポイントである、ことを教えてくれます範囲:

  • U + E000..U + F8FF
  • U + F0000..U + FFFFF
  • U + 100000..U + 10FFFF

ので、対応するPerlの正規表現は次のようになります。

my $pua = qr([\x{e000}-\x{f8ff}\x{f0000}-\x{fffff}\x{100000}-\x{10ffff}]); 

他の言語の多くは、Unicodeのサポートが類似しています(コードポイントによる文字列内の文字を含むUTF-8文字とのマッチングなど)。例えば、ここでは主に補間のため\u{...}を使用しての代わりに、\x{...}が異なるルビー、です:

not_bmp = %r([\u{10000}-\u{10FFFF}]) 
pua = %r([\u{e000}-\u{f8ff}\u{f0000}-\u{fffff}\u{100000}-\u{10ffff}]) 

のPythonだけ正確に4進数で動作エスケープ\uが、あなたはのpython3持っている場合 - またはPython2をワイドでコンパイルモード - 大文字の\Uを使用することができますが、これは正確に8つです({で可変長サポートはありません...})しているPerlやRubyなど:

not_bmp = re.compile(u'[\U00010000-\U0010ffff]') 
pua = re.compile(u'[\ue000-\uf8ff\U000f0000-\U000fffff\U00100000-\U0010ffff]') 
+0

私はBMPに関するいくつかの研究を行ってきましたが、私が受け取ったデータを気にしているようです。これ以外のデータは、間違っているかそうでなければ、私たちが保存したくないデータです。 –

+0

SQL ServerはすべてのUnicodeデータに対してUTF-16への変換を行うため、このデータをファイルからSQL Serverに送信する際に、少しのコンテキストを提供するためにデータの問題が発生しています。エンコードスイッチを適切にすることはできません。このデータは、UTF-16 Windowsマシン→UTF-8ファイル→UTF-16 SQL Server→UTF-16ファイル→UTF-8ファイル→UTF-16 SQL Serverになります。それはまったく混乱です。 UTFの私の貧弱な理解を訂正してくれてありがとう、それはまさに私が探していたものです。 –

+2

途中の何かのようなサウンドは、実際にはUTF-16をサポートせず、UCS-2のみをサポートします。とにかく、私は助けることができてうれしい。 –

3

バイトではなく文字で作業する必要があります。

コード内にデータがあり、use utf8プラグマを使用して、プログラムのソースコードがutf8であることをPerlに伝えます。この例では、コードをコピーして貼り付けることができます。

文字クラス[]\x{} escape sequenceを使用して文字列置換を行うことができます。これらは、個別の範囲だけでなく、範囲内でも使用できます。

use utf8; 

my $foo = "asfd ☃ Բարեւ ສະບາຍດີ"; 
$foo =~ s/[\x{10002b}\x{100036}]//g; 
CORE::say $foo; 

この意志出力:

asfd ☃ Բարեւ ສະບາຍດີ 

(私のSTDOUTが正常に開かれていないからだと、そこプリント警告でワイド文字もだが、のはそれを無視してみましょう)。

置き換えられた2文字は、はサンプルデータの最初の2文字です。 IDEで使用するフォントにグリフがない文字の序数が表示されるので、その文字が何であるかを簡単に知ることができます。

my font shows character ordinals

これらの文字はSupplementary Private Use Area-Bからです。 (Wikipedia

16 PUA-B U + 100000..U + 10FFFF補足私用領域-B 65,536 65,534不明

だから我々はまた、範囲を行うことができます。

my $foo = "asfd ☃ Բարեւ ສະບາຍດີ"; 
$foo =~ s/[\x{100000}-\x{10ffff}]//g; 
CORE::say $foo; 

出力:

asfd ☃ Բարեւ ສະບາຍດີ 

すべてのプライベート使用領域を取得するには、hereを列挙されている3つの範囲を含める必要があります。

/[\x{E000}-\x{F8FF}\x{F0_000}-\x{FF_FFD}\x{100_000}-\x{10f_fff}]//g; 
1

それは私用領域の六角範囲をルックアップするために持っているあなたの時間の無駄です。単に

S/\ {pをPrivate_Use} //グラム

perlunipropsは、すべてのUnicodeプロパティを与えるポッドファイルであると言います。上記のBMPプライベート使用領域だけが必要な場合は、それを参照して(プライベートのためのグレープ)、それらを照合する方法を見つけることができます。

関連する問題