rdr*_*109 10 sort unicode locale
今天,我想保留包含汉字的文件中的唯一行。我决定使用该sort实用程序,因为我熟悉该工具,并且删除文件中的重复行就像使用该-u标志一样简单。我了解到我需要更改区域设置才能sort正确使用中文字符。我注意到使用不同的区域设置会sort产生不同的行为。在这篇文章中,我展示了我的发现。
我知道删除文件中重复行的任务可以使用多种工具/编程语言来完成。虽然我感谢任何建议完成该任务的工具的人,但我更感兴趣的是了解有关语言环境的更多信息以及它们如何影响 Unix 实用程序。
\n\n以下是我的系统的区域设置。
\nlocale\nRun Code Online (Sandbox Code Playgroud)\nLANG=en_US.UTF-8\nLC_CTYPE="en_US.UTF-8"\nLC_NUMERIC="en_US.UTF-8"\nLC_TIME="en_US.UTF-8"\nLC_COLLATE="en_US.UTF-8"\nLC_MONETARY="en_US.UTF-8"\nLC_MESSAGES="en_US.UTF-8"\nLC_PAPER="en_US.UTF-8"\nLC_NAME="en_US.UTF-8"\nLC_ADDRESS="en_US.UTF-8"\nLC_TELEPHONE="en_US.UTF-8"\nLC_MEASUREMENT="en_US.UTF-8"\nLC_IDENTIFICATION="en_US.UTF-8"\nLC_ALL=\nRun Code Online (Sandbox Code Playgroud)\n考虑以下名为main.txt
\xe4\x94\x8d\n\xe4\x8f\x9d\nRun Code Online (Sandbox Code Playgroud)\nen_US.UTF-8如果我尝试使用作为我的排序$LANG对其进行排序。我失去了行号。2
sort -u main.txt\nRun Code Online (Sandbox Code Playgroud)\n\xe4\x94\x8d\nRun Code Online (Sandbox Code Playgroud)\nLANG我已经通过设置解决了这个问题zh_CN.UTF-8。
export LANG=zh_CN.UTF-8\nsort -u main.txt\nRun Code Online (Sandbox Code Playgroud)\n\xe4\x94\x8d\n\xe4\x8f\x9d\nRun Code Online (Sandbox Code Playgroud)\n我在 Stack Overflow 中创建了一个关于此问题的问题。有人建议我更改语言环境,它似乎有效,我以为我已经解决了问题,但后来我发现问题没有。2 和发行号。3(如下所述)。
\n\n现在,假设我们在文件中添加两行main.txt
\xe4\x94\x8d\n\xe4\x8f\x9d\n\n\nRun Code Online (Sandbox Code Playgroud)\n如果我在等于sort -u时执行它,我会丢失第 1 行。4.LANGzh_CN.UTF-8
export LANG=zh_CN.UTF-8\nsort -u main.txt\nRun Code Online (Sandbox Code Playgroud)\n\xe4\x94\x8d\n\n\xe4\x8f\x9d\nRun Code Online (Sandbox Code Playgroud)\n我尝试了不同的语言环境,zh.CN因为这些字符是汉字。未注释的语言环境是我尝试使用的语言环境。
grep \'^#\\?zh\' /etc/locale.gen\nRun Code Online (Sandbox Code Playgroud)\nzh_CN.GB18030 GB18030 \nzh_CN.GBK GBK \nzh_CN.UTF-8 UTF-8 \nzh_CN GB2312 \n#zh_HK.UTF-8 UTF-8 \n#zh_HK BIG5-HKSCS \n#zh_SG.UTF-8 UTF-8 \n#zh_SG.GBK GBK \n#zh_SG GB2312 \n#zh_TW.EUC-TW EUC-TW \n#zh_TW.UTF-8 UTF-8 \n#zh_TW BIG5 \nRun Code Online (Sandbox Code Playgroud)\n我注意到当设置为orsort -u时,它可以按预期工作。我通过使用或解决了这个问题。LANGzh_CN.GBKzh_CN.GB18030zh_CN.GBKzh_CN.GB18030
这是设置为 时它按预期工作的LANG证明zh_CN.GBK。
export LANG=zh_CN.GBK\nsort -u main.txt\nRun Code Online (Sandbox Code Playgroud)\n\xe4\x94\x8d\n\n\n\xe4\x8f\x9d\nRun Code Online (Sandbox Code Playgroud)\n这是设置为 时它按预期工作的LANG证明zh_CN.GB18030。
export LANG=zh_CN.GB18030\nsort -u main.txt\nRun Code Online (Sandbox Code Playgroud)\n\xe4\x94\x8d\n\n\n\xe4\x8f\x9d\nRun Code Online (Sandbox Code Playgroud)\n\n假设我们在文件中再添加两行main.txt
\xe4\x94\x8d\n\xe4\x8f\x9d\n\n\n\xe4\xb9\xa6\n\xe4\xb9\x99\nRun Code Online (Sandbox Code Playgroud)\n如果我使用zh_CN.GB18030or zh_CN.GBK,我会丢失第 1 行。6.
export LANG=zh_CN.GB18030\nsort -u main.txt\nRun Code Online (Sandbox Code Playgroud)\n\xe4\xb9\xa6\n\xe4\x94\x8d\n\n\n\xe4\x8f\x9d\nRun Code Online (Sandbox Code Playgroud)\nexport LANG=zh_CN.GBK\nsort -u main.txt\nRun Code Online (Sandbox Code Playgroud)\n\xe4\xb9\xa6\n\xe4\x94\x8d\n\n\n\xe4\x8f\x9d\nRun Code Online (Sandbox Code Playgroud)\n\n$LANG我应该使用哪个值来sort真正保留以下文件中的唯一行?
\xe4\x94\x8d\n\xe4\x8f\x9d\n\n\n\xe4\xb9\xa6\n\xe4\xb9\x99\nRun Code Online (Sandbox Code Playgroud)\n我之前表明使用zh_CN.GB18030、zh_CN.GBK或似乎不起作用。zh_CN.UTF-8zh_CN
Sté*_*las 10
sort -u输出在区域设置中整理相同(具有相同排序顺序)的每组行之一。
在 GNU 系统(使用 GNU libc 的系统)上,在大多数语言环境中,许多字符\xc2\xb9 具有未定义的排序顺序,这意味着它们最终排序相同,并且还存在显式定义为具有相同排序顺序的字符。
\n当字节无法解码为文本时,它们通常也会被忽略或被认为具有相同的排序顺序\xc2\xb2。
\n因此,为了sort -u给您基于字节到字节相等比较的独特行,无论文本使用何种编码编写,您都需要一个区域设置,其中每个字节都可以解码为一个字符和一个具有总顺序的区域设置。
最简单的方法是使用C一个字节 == 一个字符映射的区域设置(某些字节可能导致未定义的字符),并且排序基于字节值(至少在基于 ASCII 的系统上),并且是唯一的区域设置您一定可以在任何给定系统上找到它。
就您的情况而言,要了解为什么zh_CN会给您带来更好的行为,您可以查看通常在/usr/share/i18n/localeGNU 系统上的语言环境定义,zh_CN您可以在其中找到:
LC_COLLATE\ncopy "iso14651_t1_pinyin"\nEND LC_COLLATE\nRun Code Online (Sandbox Code Playgroud)\n哪里iso14651_t1_pinyin有:
copy "iso14651_t1_common"\nRun Code Online (Sandbox Code Playgroud)\n然后指定许多附加汉字的排序,而en_US仅使用iso14651_t1_common.
如果您设置LC_CTYPE(通过LANG)为 zh_CN.GB18030 或 zh_CN.GBK 并尝试处理以 UTF-8 编码的文件,sort通常无法将行解码为文本,因为 UTF-8 编码文本的字节通常不会形成有效的 GB18030 编码文本会让问题变得更糟。
在这里,如果您想获得唯一的(根据字节到字节比较)行,但也想在您的语言环境中获得“正确”排序的输出,您可以这样做:
\nLC_ALL=C sort -u your-file | sort\nRun Code Online (Sandbox Code Playgroud)\n第一个sort删除重复项,第二个根据您的区域设置排序规则对剩余行进行排序。
我们使用or +LC_ALL代替,因为它是覆盖所有内容的变量(优先于which 优先于),因此如果环境中也设置了or ,它仍然有效。LANGLC_CTYPELC_COLLATELC_ALLLC_individual_settingLANGLANGLC_COLLATE
理论上,你还可以这样做:
\nLC_ALL= LC_CTYPE=C LC_COLLATE=C sort\nRun Code Online (Sandbox Code Playgroud)\n以便仅设置“字符类型”和“排序规则”设置,而单独保留其他区域设置类别(由LANG或覆盖LC_xxx),但 所使用的其余类别sort用于LC_MESSAGES例如错误消息,如果您设置 ,则LC_CTYPE=C仅使用 US-无论如何,英语消息都可以正确显示,因为它只有 ASCII 字符。例如:
$ LC_MESSAGES=zh_CN LC_CTYPE=C sort --version\nsort (GNU coreutils) 9.1\nCopyright (C) 2022 Free Software Foundation, Inc.\n??? GPLv3+:GNU ???????? 3 ?????? <https://gnu.org/licenses/gpl.html>?\n????????:??????????????\n?????????,????????\n\n? Mike Haertel ? Paul Eggert ???\nRun Code Online (Sandbox Code Playgroud)\n您可以在以下位置找到更多详细信息:
\n\n\xc2\xb9 严格来说,主要单位不是字符,而是整理元素,它可以由多个字符组成,例如 在某些捷克语环境中ch排序的字符。hi
\xc2\xb2 请注意,某些sort实现(不是 GNU sort)也会因 NUL 字符或过长的行而阻塞。
| 归档时间: |
|
| 查看次数: |
585 次 |
| 最近记录: |