我有一組相當大(~15GB)的文字檔。這些檔案本質上是包含憑證的簡單資料庫,其中的憑證通常超出 128 個字元 ASCII 範圍(重音字元等)。
當我嘗試使用以下方法對其中一些文件進行排序時:
sort -u input.txt -o output.txt
....我收到以下錯誤:
sort: string comparison failed: Invalid or incomplete multibyte or wide character
sort: Set LC_ALL='C' to work around the problem.
我讀過很多關於 using 如何LC_ALL=C
加速處理字元的命令,例如sort
和grep
,包括史蒂芬·查澤拉斯 (Stephane Chazelas) 的精彩回答關於這個主題,但我特別擔心在我的資料集上使用它的影響。
在這些文件上運行LC_ALL=C sort -u
是否可能會去除其中的任何非 ASCII 字元?
如果是,那麼我可以做什麼來修復/刪除所有“無效或不完整的多字節或寬字符LC_ALL=C
「從這些文件中,允許我在不使用? 的情況下對它們進行排序。
答案1
在這些檔案上執行 LC_ALL=C sort -u 是否可能會移除其中的任何非 ASCII 字元?
在這種情況下,不 –sort
將直接處理位元組值,而不是嘗試將它們轉換為字元。
然而,這並不一定適用於其他工具。用 C(語言)編寫的程式最有可能出現這種行為。使用具有強烈位元組與字元區別的語言(例如 Python 3)編寫的程式應該完全拒絕接受不符合字元集的輸入。我當然可以想像編寫糟糕的程式會忽略錯誤並輸出 a 或 a ?
。
如果是,那麼我可以做什麼來修復/刪除這些文件中的所有“無效或不完整的多字節或寬字符”,從而允許我在不使用 LC_ALL=C 的情況下對它們進行排序?
確保它們都使用相同的檔案編碼(最好是 UTF-8),並且您的區域設定使用相同的編碼。對於有效的 UTF-8 文件,無論它有多大,都不會發生該錯誤。
答案2
因為我最終需要透過許多不同的 Bash 工具(如、 、sort
和grep
)來傳輸我的文件,所以我決定採用已接受答案中指出的「正確的解決方案」更安全;首先將它們全部轉換為 UTF-8。這最終比預期的要困難一些,尤其是因為我花了一段時間才意識到確定文件是 ASCII 還是 UTF-8 並不可靠(因為它不檢查整個文件),所以我把這個答案放在這裡供後代使用。awk
wc
tr
file
要明確確定檔案的編碼方式,首先確保該uchardet
軟體包是透過 Cygwin 安裝程式安裝的,或者apt-cyg,然後運行:
uchardet *.txt
或者,如果您沒有使用 Cygwin:
chardet *.txt
chardet
將列出的所有檔案移動到它們自己的資料夾中,並在該資料夾中ASCII
執行以下循環:for
for i in *.txt; do iconv -f ASCII -t UTF-8 "$i" >> "${i%.txt}_utf.txt"; done;
它將循環遍歷.txt
資料夾中的所有檔案並建立它們的 UTF-8 版本並utf
添加後綴。
再次運行uchardet *.txt
可能仍會顯示某些文件為ASCII
.發生這種情況是因為 ASCII 是 UTF-8 的子集,並且簡單的意思就是這些檔案不包含 128 位元 ASCII 範圍之外的字元。
您現在應該能夠運行sort
而無需使用LC_ALL=C
.