如何使用 >> 双尖括号对行进行排序?

如何使用 >> 双尖括号对行进行排序?

似乎sort在诸如以下的线路上表现得很奇怪>>b

$ cat test
a
>>b
b
c
>
>>

$ sort test
>
>>
a
b
>>b
c

我希望该>>b行是第三行输出,sort但它是第五行。为什么它会这样做,有没有办法sort给出我的预期输出?

我正在使用 GNU/Linux Ubuntu 16.04。

答案1

现代语言环境中的排序算法非常复杂。

每个角色(实际上整理元素它可以由几个字符的序列组成,例如捷克语ch)被赋予了一些整理权重决定它们的排序顺序。

比较两个字符串时,首先使用所有字符的第一个权重,然后使用其他权重来确定两个字符串与第一个权重排序相同的情况。

例如,在许多语言环境中,eéE具有相同的基本的重量(它们属于相同的等价类,它们都匹配[=e=])。

因此,当比较例如echoété和 时Enter,在第一遍中,eé具有E相同的主要权重,第二个字符将决定顺序(cbefore nbefore t)。

在第一遍之后比较été, Été, , 时,它们的排序相同,因此我们使用次要权重来使用第二遍。Ete在典型的 GNU 语言环境中,拉丁脚本字符的第二个权重用于确定重音的优先级(无重音优先,然后是锐音、重音、短音、抑音音……)。然后,我们需要使用第三个权重来决定été和 ,Été并且这将基于大小写(在大多数语言环境中先小写)。甚至有些字符最终排序相同,因为它们的权重都相同。

它用于以与字典类似的方式对文本进行排序,就像人类所做的那样。

在字典中,您会发现空格和大多数标点符号也被忽略。例如de factodebut和之间排序devoid。空格字符的第一个权重是 IGNORE。

/usr/share/i18n/locales/iso14651_t1_common在 GNU 系统上,您将在(路径可能因发行版而异)中找到定义的核心排序规则。在那里,您将看到:

ifdef UPPERCASE_FIRST
<CAP>
else
<MIN>
endif
[...]
ifdef UPPERCASE_FIRST
[...]
<MIN> # 10
[...]
else
[...]
<CAP> # 9
[...]
endif

[...]
order_start <SPECIAL>;forward;backward;forward;forward,position
<U0020> IGNORE;IGNORE;IGNORE;<U0020> # 32 <SP>
[...]
<U003E> IGNORE;IGNORE;IGNORE;<h> # 140 >
[...]
ifdef DIACRIT_FORWARD
order_start <LATIN>;forward;forward;forward;forward,position
else
order_start <LATIN>;forward;backward;forward;forward,position
endif
[...]
<U0065> <e>;<BAS>;<MIN>;IGNORE # 259 e
<U00E9> <e>;<ACA>;<MIN>;IGNORE # 260 é
[...]
<U0045> <e>;<BAS>;<CAP>;IGNORE # 577 E
<U00C9> <e>;<ACA>;<CAP>;IGNORE # 578 É

这说明了我们刚才所说的。两者的空间和>前 3 个权重都设置为IGNORE。仅对于前 3 个权重排序相同的字符串,才会考虑它们的相对顺序(>在空格之前,因为它将<h>在未指定的整理符号之前列出<U0020>)。

在定义的语言环境中UPPERCASE_FIRST(例如/usr/share/i18n/locales/tr_TR),大写字母将首先出现(在第三遍中。与DIACRIT_FORWARD某些语言环境一样,de_DE可以决定颠倒第二遍的变音符号顺序

>并 在第 1、23>>进行相同的排序。在第四个中在之前排序,因为空字符串在所有内容之前排序。>>>

>>b之后排序,b因为它们在前 3 遍中排序相同,但在第四遍中b为 IGNORE,因此>更大。它比c第一遍(>忽略和b之前)要少c......你明白了。

现在,如果您查看C区域设置定义。简单多了。只有一个权重,并且该权重基于从 U+0000 到 U+10FFFF 的代码点值。因此,SPC(U+0020) 排序在>(U+003E) 之前,(U+003E) 排序在b(U+0062) 之前,而 (U+0063) 排序在c(U+0063) 之前。没有一个角色会被忽视。

请注意,至少对于 GNU libc,当涉及比较函数(strcoll()以及 所使用的 co. sort)时,C 语言环境定义文件中定义的顺序将被忽略。无论 的值如何LC_CTYPE,与LC_COLLATE=Cstrcoll()都等同于strcmp()。因为比较始终针对字节值,即使这些字节对应于 unicode 代码点以相反方式排序的字符(例如 ISO-8859-15 字符集中的 0xA4 U+20AC EURO SIGN 与 A5 U+00A5 YEN SIGN) ,因此LC_ALL=C sortLC_COLLATE=C sortLC_ALL如果没有另外设置)将具有相同的效果。

答案2

sort(1)手册页:

   *** WARNING *** The locale specified by the  environment  affects  sort  order.   Set
   LC_ALL=C to get the traditional sort order that uses native byte values.

因此,要按字节值排序,请使用:

LC_ALL=C sort test

否则,sort将忽略前导字符,直到遇到可以排序的键,这就是>>bb最终彼此相邻的原因。

相关内容