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.

我读过很多关于如何使用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 ?

如果是,那么我可以做什么来修复/删除这些文件中的所有“无效或不完整的多字节或宽字符”,以便我在不使用 LC_ALL=C 的情况下对它们进行排序?

确保它们都使用相同的文件编码(最好是 UTF-8),并且您的语言环境使用相同的编码。无论有效的 UTF-8 文件有多大,都不应该出现此错误。

答案2

由于我最终需要通过许多不同的 Bash 工具(如、、和)来传输文件,因此sort我决定采用grep已接受答案中指出的“正确解决方案”更为安全;首先将它们全部转换为 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添加后缀的 UTF-8 版本。

再次运行uchardet *.txt可能仍会显示某些文件为ASCII。发生这种情况是因为 ASCII 是 UTF-8 的子集,并且只是意味着这些文件不包含 128 位 ASCII 范围之外的字符。

现在您应该能够运行sort而不需要使用LC_ALL=C

相关内容