上下文

上下文
  • 上下文
  • 发现了问题
    • 问题编号1
    • 问题编号2
    • 问题编号3
  • 问题

上下文

今天,我想保留包含汉字的文件中的唯一行。我决定使用该sort实用程序,因为我熟悉该工具,并且删除文件中的重复行就像使用该-u标志一样简单。我了解到我需要更改区域设置才能sort正确使用中文字符。我注意到使用不同的区域设置sort会有不同的行为。在这篇文章中,我展示了我的发现。

我知道删除文件中重复行的任务可以使用多种工具/编程语言来完成。虽然我感谢任何建议完成该任务的工具的人,但我更感兴趣的是了解有关语言环境以及它们如何影响 Unix 实用程序的更多信息。

发现了问题

问题编号1

以下是我的系统的区域设置。

locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

考虑以下名为main.txt


如果我尝试使用en_US.UTF-8as my对其进行排序$LANG。我失去了行号。 2

sort -u main.txt

LANG我已经通过设置解决了这个问题zh_CN.UTF-8

export LANG=zh_CN.UTF-8
sort -u main.txt

我创建一个问题关于 Stack Overflow 中的这个问题。有人建议我更改语言环境,它似乎有效,我以为我已经解决了问题,但后来我发现问题没有。 2 和问题编号。 3(如下所述)。

问题编号2

现在,假设我们在文件中添加两行main.txt


答案1

sort -u输出在区域设置中整理相同(具有相同排序顺序)的每组行之一。

在 GNU 系统(使用 GNU libc 的系统)上,在大多数语言环境中,许多字符 1 具有未定义的排序顺序,这意味着它们最终排序相同,并且还存在显式定义为具有相同排序顺序的字符。

当字节无法解码为文本时,它们通常也会被忽略或被认为具有相同的排序顺序²。

因此,为了sort -u给您基于字节到字节相等比较的独特行,无论文本使用何种编码编写,您都需要一个区域设置,其中每个字节都可以解码为一个字符和一个具有总顺序的区域设置。

最简单的方法是使用C有一个字节 == 一个字符映射的区域设置(某些字节可能导致不明确的字符),排序基于字节值(至少在基于 ASCII 的系统上),并且是您保证在任何给定系统上找到的唯一区域设置。

就您的情况而言,要了解为什么zh_CN会给您带来更好的行为,您可以查看通常在/usr/share/i18n/localeGNU 系统上的语言环境定义zh_CN,您可以在其中找到:

LC_COLLATE
copy "iso14651_t1_pinyin"
END LC_COLLATE

哪里iso14651_t1_pinyin有:

copy "iso14651_t1_common"

然后指定许多附加汉字的排序,而en_US仅使用iso14651_t1_common.

如果您设置LC_CTYPE(通过LANG)为 zh_CN.GB18030 或 zh_CN.GBK 并尝试处理以 UTF-8 编码的文件,sort通常无法将行解码为文本,因为 UTF-8 编码文本的字节通常不形成有效的形式GB18030 编码的文本会让问题变得更糟。

在这里,如果您想获得唯一的(根据字节到字节比较)行,但也想在您的语言环境中获得“正确”排序的输出,您可以这样做:

LC_ALL=C sort -u your-file | sort

第一个sort删除重复项,第二个根据您的区域设置排序规则对剩余行进行排序。

我们使用LC_ALL而不是LANGor LC_CTYPE+ ,LC_COLLATE因为这是覆盖所有内容的变量(LC_ALL优先于LC_individual_settingwhich 优先于LANG),所以如果LANGorLC_COLLATE也以其他方式在环境中设置,它仍然有效。

理论上,你还可以这样做:

LC_ALL= LC_CTYPE=C LC_COLLATE=C sort

以便仅设置“字符类型”和“排序规则”设置,而单独保留其他区域设置类别(由LANG或覆盖LC_xxx),但 所使用的其余类别sort用于LC_MESSAGES例如错误消息,如果您设置LC_CTYPE=C,则仅使用 US-无论如何,英语消息都可以正确显示,因为它只有 ASCII 字符。例如:

$ LC_MESSAGES=zh_CN LC_CTYPE=C sort --version
sort (GNU coreutils) 9.1
Copyright (C) 2022 Free Software Foundation, Inc.
??? GPLv3+:GNU ???????? 3 ?????? <https://gnu.org/licenses/gpl.html>?
????????:??????????????
?????????,????????

? Mike Haertel ? Paul Eggert ???

您可以在以下位置找到更多详细信息:


严格来说,主要单位不是特点整理元素它可以由多个类似的字符组成, ch例如在某些捷克地区之间hi在某些捷克地区中。

² 请注意,某些sort实现(非 GNU sort)也会因 NUL 字符或过长的行而阻塞。

相关内容