为什么 sed 不执行 grep(以及 sed、awk)的区域设置排序规则文件中定义的操作?

为什么 sed 不执行 grep(以及 sed、awk)的区域设置排序规则文件中定义的操作?

拥有一个包含所有(可打印)ascii 字符的文件:

$ printf '%b' "$(printf '\\U%x\n' {32..126})" > file

可以对其进行排序(使用 tr 将长输出减少到一行):

$ sort file | tr -d '\n'
 !"#%&'()*+,-./:;<=>?@[\]^_`{|}~$0123456789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ

显示在使用 en_US.utf8 语言环境的 Debian buster 计算机上,整理排序(针对单个字符)首先是所有标点符号,然后是数字,然后是混合大小写字母。即:aAbB,小写和大写字母在一起。

让我们假设这是正确的,并且是用户(我)希望进行整理的情况。

然而,在同一个系统上,没有任何其他更改,会发生这种情况:

$ grep '[a-z]' file | tr -d '\n'
abcdefghijklmnopqrstuvwxyz

也就是说,范围a-z被某些东西转换为小写 ASCII 字母。

谁在进行翻译以及如何控制或更改翻译?

我不是问什么是小写字母,也不是问 [az] 应该是什么意思,或者有人想要这个意思。

我期望这是一个开始于并结束于 的[a-z]范围az 按整理顺序

我知道其他一些用户希望其[a-z]含义与任何语言环境中的“小写”相同。默认情况下,我可能会“忍受这一点”。

但如果需要的话,我该如何控制和/或改变它呢?改变它的旋钮在哪里?

不,更改整理文件并没有帮助,有些东西超出了这个范围,并强制执行个人观点,即[a-z]在所有语言环境中 a 必须始终表示 ASCII 小写。

答案1

我读了什么POSIX 状态。我的解释是有两个不等价的概念:

  • 整理序列(整理序列)
  • 整理顺序

相关片段[强调我的]:

LC_COLLATE类别提供了整理顺序POSIX.1-2017 的 Shell 和实用程序卷中众多实用程序的定义(lssort等)、正则表达式匹配(请参阅正则表达式)以及POSIX.1- 的系统接口卷中的strcoll()strxfrm()wcscoll()和函数wcsxfrm()2017年。

A整理顺序定义应定义区域设置中整理元素(字符和多字符整理元素)之间的相对顺序。该顺序以排序规则值的形式表示;也就是说,通过为每个元素分配一个或多个排序规则值(也称为排序规则权重)。 […]

关键字order_start应位于整理顺序条目并定义该条目的权重数量整理顺序定义和其他排序规则。

整理顺序本节中定义的内容会影响正则表达式中括号表达式的解释(请参阅 RE 括号表达式)。

对于sort排序顺序很重要,即权重。对于grep '[a-z]'整理顺序而言,即整理顺序条目的顺序。

不幸的是只有整理顺序是明确定义,因此没有明确表明排序顺序是不同的概念。

排序顺序
排序元素的相对顺序由LC_COLLATE当前区域设置中的类别设置确定。核对序列用于排序,并根据分配给每个核对元素的核对权重来确定。在没有权重的情况下,排序顺序是在类别中的关键字order_start之间指定排序元素的顺序。order_endLC_COLLATE


在我的 Debian 9 中,当谈到 时LC_COLLATE,许多语言环境最终都会引用iso14651_t1_common(即/usr/share/i18n/locales/iso14651_t1_common)。文件的相关片段如下所示:

<U0061> <a>;<BAS>;<MIN>;IGNORE # 198 a
<U00AA> <a>;<PCL>;<EMI>;IGNORE # 199 ª
<U00E1> <a>;<ACA>;<MIN>;IGNORE # 200 á
[…]
<U0062> <b>;<BAS>;<MIN>;IGNORE # 233 b
<U0253> <b>;<CRL>;<MIN>;IGNORE # 234 ɓ
<U1E03> <b>;<PCT>;<MIN>;IGNORE # 235 ḃ
[…]
<U007A> <z>;<BAS>;<MIN>;IGNORE # 507 z
<U017A> <z>;<ACA>;<MIN>;IGNORE # 508 <z'>
<U017E> <z>;<CAR>;<MIN>;IGNORE # 509 <z<>
[…]
<U0041> <a>;<BAS>;<CAP>;IGNORE # 517 A
<U00C1> <a>;<ACA>;<CAP>;IGNORE # 518 Á
<U00C0> <a>;<GRA>;<CAP>;IGNORE # 519 À
[…]
<U0042> <b>;<BAS>;<CAP>;IGNORE # 550 B
<U1E02> <b>;<PCT>;<CAP>;IGNORE # 551 <B.>
<U1E04> <b>;<BPT>;<CAP>;IGNORE # 552 Ḅ
[…]
<U005A> <z>;<BAS>;<CAP>;IGNORE # 813 Z
<U0179> <z>;<ACA>;<CAP>;IGNORE # 814 <Z'>
<U017D> <z>;<CAR>;<CAP>;IGNORE # 815 <Z<>

这是整理顺序[a-z]不包含,因为( )A的条目不在和 的条目之间。A<U0041>az

a和的条目仍然A指定相同的整理符号<a>。类似地bB指定<b>.这转化为权重:

权重应表示为字符(区域设置定义中指定的任何形式)、<collating-symbol>s、<collating-element>s、省略号或特殊符号IGNORE。单个字符 a<collating-symbol>或 a<collating-element>应表示字符中的相对位置整理顺序字符或符号,而不是字符或字符本身。因此,不是为权重分配绝对值,而是使用基于其在字符中的顺序分配给整理元素的相对顺序值来表达特定的权重整理顺序

在文件中<a><b>是按以下顺序定义的:

collating-symbol <a>
collating-symbol <b>

这使得相关子序列整理顺序aAbB。这才是重要的sort


为了确认这一点,我(暂时)移动了以下整理顺序条目

<U004B> <k>;<BAS>;<CAP>;IGNORE # 649 K

到 的条目之前的位置v,即介于a和之间的某个位置z。我用 重建了我的语言环境locale-gen。现在sort file | tr -d '\n'仍然返回…iIjJkKlLmM…(权重没有改变,排序规则没有改变),但grep '[a-z]' file | tr -d '\n'产生:

Kabcdefghijklmnopqrstuvwxyz

这意味着我通过更改排序顺序K来制作属于。[a-z]

如果您想grep '[a-z]' file | tr -d '\n'返回 的排列aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ而不是abcdefghijklmnopqrstuvwxyz,那么您需要使用具有不同排序顺序的语言环境。它可能是自定义区域设置。

相关内容