使用 LC_COLLATE 指定排序顺序,因此小写字母在大写字母之前

使用 LC_COLLATE 指定排序顺序,因此小写字母在大写字母之前

给定文件:

$ cat file
1
a
C
B
2
c
3
A
b

默认情况下sort将:

$ sort file
1
2
3
a
A
b
B
c
C

这样LC_COLLATE=C将按大写字母在小写字母之前排序:

$ LC_COLLATE=C sort file
1
2
3
A
B
C
a
b
c

是否可以排序以颠倒大小写顺序,即数字,小写然后大写?

答案1

我不知道有任何语言环境默认按该顺序排序。解决方案是创建具有自定义排序顺序的自定义区域设置。如果四年后有人想要以定制方式进行排序,这就是诀窍。

绝大多数语言环境不指定自己的排序顺序,而是复制中定义的排序顺序,/usr/share/i18n/locales/iso14651_t1_common以便您要编辑。iso14651_t1_common我建议您复制一份,而不是通过修改原始文件来更改几乎每个区域设置的排序顺序。有关排序顺序如何工作以及如何在$HOME没有 root 访问权限的目录中创建自定义区域设置的详细信息,请参阅在这个类似问题的答案中

看看aA是如何根据它们在 中的条目进行排序的iso14651_t1_common

<U0061> <a>;<BAS>;<MIN>;IGNORE # 198 a
<U0041> <a>;<BAS>;<CAP>;IGNORE # 517 A

b并且B是相似的:

<U0062> <b>;<BAS>;<MIN>;IGNORE # 233 b
<U0042> <b>;<BAS>;<CAP>;IGNORE # 550 B

我们看到,在第一遍中, 和 都a具有A整理符号<a>,而 和bB具有整理符号<b>。由于<a>出现<b>在之前iso14651_t1_commona并且和A之前并列。第二遍不会打破联系,因为所有四个字符都有整理符号,但在第三遍期间,联系被解决,因为小写字母的整理符号出现在第 3467 行,在大写字母的整理符号之前(第 3488 行) 。所以排序顺序最终为, , , 。bB<BAS><MIN><CAP>aAbB

交换第一个和第三个整理符号将首先按大小写(先小后大)对字母进行排序,然后按重音(<BAS>表示非重音),然后按字母顺序排序。 然而<MIN><CAP>都位于数字之前,因此这会产生将数字放在字母后面的不良效果。

在制作时将数字放在第一位的最简单方法全部小写字母在前全部大写字母的作用是通过将所有字母设置为等于 来强制在第一次比较期间将所有字母打成平局<a>。为了确保它们在大小写内按字母顺序排序,请将最后一个整理符号更改为IGNORE当前的第一个整理符号。遵循这种模式,a将变成:

<U0061> <a>;<BAS>;<MIN>;<a> # 198 a

A会成为:

<U0041> <a>;<BAS>;<CAP>;<a> # 517 A

b会成为:

<U0062> <a>;<BAS>;<MIN>;<b> # 233 b

B会成为:

<U0042> <a>;<BAS>;<CAP>;<b> # 550 B

其余字母依此类推。

创建 的自定义版本后iso14651_t1_common,请按照中的说明进行操作上面链接的答案编译您的自定义语言环境。

答案2

设置LC_COLLATE=C并不总是足以将大写字母排序在小写字母之前。您可能需要设置LC_ALL=C.

这还将考虑非字母数字甚至不可打印的字符,但如果您不希望有选项-d-i(在 中描述man sort)将其关闭。

不过,对于多字节输入(例如带有非 ASCII 字符的 UTF-8),它可能会严重失败。

为了在大写(按顺序)之前获得小写(按顺序),我能想到的最好的方法是在排序之前反转所有字母的大小写,然后将它们反转回来,这不涉及打破成熟的编程语言然后。

tr 'a-zA-Z' 'A-Za-z' < file | LC_ALL=C sort | tr 'a-zA-Z' 'A-Za-z'

答案3

我不是专家,但我从未见过像这样定义排序规则的语言环境。 AFAIK 这个排序规则仅在 C 中基于ASCII 值。 (通常我会通过脚本解决这个问题。)

然而,我从来没有这样做过,但你可能想看看本地定义(1)语言环境(5)联机帮助页以了解如何定义语言环境并最终定义您自己的语言环境。

另外不要忘记,如果有任何变音符号或特殊字符,C 语言环境不会按照您的意愿处理它们。例如,它不会放置á“near”aŁ“near” L。在这种情况下,语言的本地语言环境可能是更好的起点。

答案4

LC_COLLATE="en_US.UTF-8" sort file

相关内容