LC_ALL=C 是否具有破壞性?

LC_ALL=C 是否具有破壞性?

我有一組相當大(~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加速處理字元的命令,例如sortgrep,包括史蒂芬·查澤拉斯 (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 工具(如、 、sortgrep)來傳輸我的文件,所以我決定採用已接受答案中指出的「正確的解決方案」更安全;首先將它們全部轉換為 UTF-8。這最終比預期的要困難一些,尤其是因為我花了一段時間才意識到確定文件是 ASCII 還是 UTF-8 並不可靠(因為它不檢查整個文件),所以我把這個答案放在這裡供後代使用。awkwctrfile

要明確確定檔案的編碼方式,首先確保該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.

相關內容