web-dev-qa-db-ja.com

ファイル内の奇妙なキャラクター

奇妙な文字を含むUTF-8ファイルがあります。

<96>

これはviでの表示方法です

vi screenshot

geditでの表示方法

gedit screenshot

libreOfficeでどのように表示されるか

LibreOffice screenshot

そのため、次のような一連の基本的なUnixツールの動作がおかしくなります。

  1. cat fileキャラクターを消滅させ、moreも同様に
  2. Vi/vim内でコピーして貼り付けることはできません-自分自身を見つけることさえできません
  3. grepは、文字が存在しないかのように、何も表示しません。

プログラムfileは正常に動作し、UTF-8ファイルとして認識します。また、ファイルの性質上、ウェブからのコピーアンドペーストによるものである可能性が高く、キャラクターは最初はEMDASHを表していました。

私の基本的な質問は:

  1. このファイルに問題はありますか?
  2. 同じファイル内の他の出現箇所を検索するにはどうすればよいですか?
  3. 同じ問題/文字が含まれている可能性がある他のファイルをgrepするにはどうすればよいですか?

ファイルはここにあります: file.txt

6
Paulo Ney

このファイルには、バイトC2 96が含まれています。これは、コードポイントU + 0096の TF-8 エンコーディングです。そのコードポイントは C1制御文字 の1つであり、一般にSPAの「ガードされた領域の開始」(または「保護された領域」)と呼ばれます。これは現代のシステムにとって有用な文字ではありませんが、そこにあることは有害である可能性は低いです。

これの元のソースは、途中で誤ってトランスコードされた一部のシングルバイト8ビットエンコーディングのバイト0x96である可能性があります。おそらくこれは元々 Windows CP1252 enダッシュ "–"であり、そのエンコーディングにバイト値96が含まれています。他のほとんどのもっともらしい候補は、80-9Fの位置にコントロールセットがあり、UTFに変換されています- 8ラテン-1( ISO/IEC 8859-1 )であるかのように、これは珍しいことではありません。これにより、バイトが制御文字として解釈され、見たとおりに変換されます。


このファイルは、glibcの一部であるiconvツールで修正できます。

iconv -f utf-8 -t iso-8859-1 < mwe.txt | iconv -f cp1252 -t utf-8

私のためにあなたの最小限の例の正しいバージョンを生成します。これは、最初にUTF-8をラテン1に変換し(以前の誤訳を反転)、次にthatをcp1252として再解釈して、UTFに戻します。 -8正しく。

ただし、実際のファイルの他の内容によって異なります。 Latin-1以外の文字がある場合、最初のステップでそれらを正しくエンコードできないため、失敗します。

Iconvがない場合、または実際のファイルで機能しない場合は、sedを使用してバイトを直接置き換えることができます。

LC_ALL=C sed -e $'s/\xc2\x96/\xe2\x80\x93/g' < mwe.txt

これは、C2 96をUTF-8 en dashエンコーディングE2 80 93に置き換えます。あなたはそれを例えばに置き換えることもできます\xe2\x80\x93--に変更して、ハイフンを1つまたは2つ。


同様の方法でgrepできます。実際のバイトを読み取るためにLC_ALL=Cを使用しており、grepが物事を解釈しないようにしています。

LC_ALL=C grep -R $'\xc2\x96` .

これらのバイトが表示されるこのディレクトリの下のあらゆる場所にリストされます。バイナリファイルにはバイトのペアがかなり頻繁に含まれるため、コンテンツが混在している場合は、テキストファイルのみに制限することをお勧めします。

27
Michael Homer

0x96はWindowsコードページ1252のenダッシュです。その前のc2バイトは、全角文字のデフォルトの最初のバイトのようです。他の誰かがそれについてより正確に説明することができます。

他の出現箇所を検索するには、コマンドモードでカーソルをその上に置き、yl(1文字をヤンク)を押してから、/<Ctrl>+r"と入力します。 (ctrl + rを使用すると、レジスタの内容をコマンドに挿入できます。"レジスタは、最後にヤンクされたものです)。

端末でレンダリングする場合は、2つのハイフンに置き換えてください。それがあなたが持っているbibtexファイルであるならば、2つのハイフンはそれをキーインする適切な方法です。

キャラクターの出現をどのように見つけることができるかを示すために、xxdのようなhexdumpツールを介してパイプすることができます。

$ cat tmp | xxd | grep c296
00000000: 7061 6765 733d 7b31 c296 3935 7d2c 0a70  pages={1..95},.p
00000020: 6765 733d 7b31 c296 3935 7d2c 0a70 6167  ges={1..95},.pag
00000040: 733d 7b31 c296 3935 7d2c 0a70 6167 6573  s={1..95},.pages
00000060: 7b31 c296 3935 7d2c 0a70 6167 6573 3d7b  {1..95},.pages={
00000080: c296 3935 7d2c 0a70 6167 6573 3d7b 31c2  ..95},.pages={1.
00000090: 9639 357d 2c0a 7061 6765 733d 7b31 c296  .95},.pages={1..
000000b0: 357d 2c0a 7061 6765 733d 7b31 c296 3935  5},.pages={1..95
000000d0: 2c0a 7061 6765 733d 7b31 c296 3935 7d2c  ,.pages={1..95},
000000f0: 7061 6765 733d 7b31 c296 3935 7d2c 0a70  pages={1..95},.p
00000110: 6765 733d 7b31 c296 3935 7d2c 0a70 6167  ges={1..95},.pag
00000130: 733d 7b31 c296 3935 7d2c 0a70 6167 6573  s={1..95},.pages
00000150: 7b31 c296 3935 7d2c 0a70 6167 6573 3d7b  {1..95},.pages={
2
user38573

ファイル内のテキストはpages = {1113},です。はい、数字1113のように見えますが、実際には最初の1の後に別の文字があります。そして、はい、このWebページの編集リンクから文字列をコピーアンドペーストして、エンコードされた文字を取得できます。

いくつかのツールで文字列の内部を見ることができます:

$ a='pages = {1113},'

または、明示的に明確にして、編集ページを使用せずに簡単にコピーして貼り付けることができるようにします。

$ a=$(printf 'pages = {1\xc2\x96113},') 

$ echo "$a" | od -An -tx1c
  70  61  67  65  73  20  3d  20  7b  31  c2  96  31  31  33  7d
   p   a   g   e   s       =       {   1 302 226   1   1   3   }
  2c  0a
   ,  \n

$ echo "$a" | sed -n l
pages = {1\302\226113},$

$ echo "$a" | xxd
00000000: 7061 6765 7320 3d20 7b31 c296 3131 337d  pages = {1..113}
00000010: 2c0a

したがって、文字は2バイトの値c2 96(16進数)または302 226(8進数)です。
これは、おそらく96のバイト値のUTF-8エンコーディングであるか、Unicode文字U-0096として表現されています。

その値は、現在のところUTF-8、より良いのはISO-8859-1で、C1領域の制御文字( Wikipedia page )および( nicode PDF )128から159までの10進数です。具体的には、U-0096は「START OF GUARDED AREA」または[〜#〜] spa [〜#〜]と呼ばれます。

その値(12月150日)はASCII範囲(0-127)を超えており、(以前は)使用されたコードページに応じていくつかの文字を表すために使用されていました。これは、以前はダッシュ(範囲1-113をマークする)で、Windows-1252( Microsoftページ )( Wikipedia 1252 )でエンコードされ、enダッシュ(2つのダッシュenem)( Wikipedia en dash )または、簡単に言えば、ダッシュ(-)。


Q1:このファイルに問題はありますか?

実際には、制御文字は有効な文字であり、めったに使用されませんが、それでも有効です。

ただし、編集を簡単にするために、ダッシュに置き換えることができます。

<file.txt sed 's/\xc2\x96/-/'

Q2-同じファイル内の他の出現箇所を検索するにはどうすればよいですか?

sed -n '/\xc2\x96/p'             # will print lines that contain that character.

または、grepは文字を検索し(文字は印刷できないため、色のハイライトは表示されません)、行を印刷します。

c="$(printf "\U96")" ; grep "$c" file.txt

より広義には、その制御文字範囲内のすべての文字を見つけ、そのような文字を含むファイルをリストします。

grep -rlP "[\x80-\x9f]"    

Q3-同じ問題/文字が含まれている可能性がある他のファイルをgrepするにはどうすればよいですか?

これは、文字に一致するファイルを一覧表示します(-l)。

grep -rlP "\x96"
1
Isaac