文件中的奇怪字元
我有一個 UTF-8 文件,其中包含一個奇怪的字元——對我來說就像
<96>
這就是它的顯示方式
vi
以及它是如何出現的
gedit
以及它在 LibreOffice 下的顯示方式
這使得一系列基本的 Unix 工具行為不端,包括:
cat file
使角色消失,more
以及- 我無法在 vi/vim 中複製和粘貼——它甚至找不到自己
grep
也無法顯示任何內容,就好像該角色不存在一樣。該程序
file
執行良好,並將其辨識為 UTF-8 文件。我也知道,由於文件的性質,它很可能來自網路上的複制和粘貼,並且該字元最初代表 EMDASH。我的基本問題是:
- 這個文件有什麼問題嗎?
- 如何在同一文件中搜尋它的其他出現?
- 如何查找可能包含相同問題/字元的其他文件?
該文件可以在這裡找到:file.txt
該文件包含 bytes
C2 96
,它們是程式碼點 U+0096 的UTF-8編碼。該程式碼點是C1 控製字元之一,通常稱為 SPA“保護區域開始”(或“保護區域”)。這對於任何現代系統都不是一個有用的字元,但它的存在不太可能有害。最初的來源可能是某個單字節 8 位編碼中的字節 0x96,該字節在途中某處被錯誤地轉碼。可能這最初是一個Windows CP1252破折號“–”,它在該編碼中具有字節值 96 - 大多數其他合理的候選者在位置 80-9F 具有控制集 - 它已被翻譯為 UTF-8,就好像它是拉丁語一樣 - 1 ( ISO/IEC 8859-1 ),這並不罕見。如您所見,這將導致字節被解釋為控製字元並相應地進行翻譯。
您可以使用該工具修復此文件,該
iconv
工具是 glibc 的一部分。iconv -f utf-8 -t iso-8859-1 < mwe.txt | iconv -f cp1252 -t utf-8
為我生成您的最小範例的正確版本。其工作原理是首先將 UTF-8 轉換為 latin-1(反轉之前的誤譯),然後將其重新解釋為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 破折號編碼E2 80 93
。您也可以通過將其更改\xe2\x80\x93
為--
.你可以用類似的方式 grep。我們
LC_ALL=C
用來確保我們正在讀取實際字節,而不是grep
解釋:LC_ALL=C grep -R $'\xc2\x96` .
將在此目錄下的所有位置列出這些字節出現。如果您有混合內容,您可能希望將其限制為僅文本文件,因為二進製文件將相當頻繁地包含任何字節對。