I read what POSIX states. My interpretation is there are two non-equivalent concepts:
- collation sequence (collating sequence)
- collation order
Relevant fragments [emphasis mine]:
LC_COLLATE category provides a collation sequence definition for numerous utilities in the Shell and Utilities volume of POSIX.1-2017 (
sort, and so on), regular expression matching (see Regular Expressions), and the
wcsxfrm() functions in the System Interfaces volume of POSIX.1-2017.
A collation sequence definition shall define the relative order between collating elements (characters and multi-character collating elements) in the locale. This order is expressed in terms of collation values; that is, by assigning each element one or more collation values (also known as collation weights). […]
order_start keyword shall precede collation order entries and also define the number of weights for this collation sequence definition and other collation rules.
The collation order as defined in this section affects the interpretation of bracket expressions in regular expressions (see RE Bracket Expression).
sort the collation sequence matters, i.e. the weights. For
grep '[a-z]' the collation order matters, i.e. the order of collation order entries.
Unfortunately only the collation sequence is defined explicitly, so there is no clear indication the collation order is a different concept.
The relative order of collating elements as determined by the setting of the
LC_COLLATE category in the current locale. The collation sequence is used for sorting and is determined from the collating weights assigned to each collating element. In the absence of weights, the collation sequence is the order in which collating elements are specified between
order_end keywords in the
In my Debian 9, when it comes to
LC_COLLATE, many locales eventually refer to
/usr/share/i18n/locales/iso14651_t1_common). The relevant fragment of the file looks like this:
<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<>
This is the collation order.
[a-z] does not contain
A because the entry for
<U0041>) is not between the entries for
Still the entries for
A specify the same collating symbol
<b>. This translates to weights:
Weights shall be expressed as characters (in any of the forms specified in Locale Definition),
<collating-element>s, an ellipsis, or the special symbol
IGNORE. A single character, a
<collating-symbol>, or a
<collating-element> shall represent the relative position in the character collating sequence of the character or symbol, rather than the character or characters themselves. Thus, rather than assigning absolute values to weights, a particular weight is expressed using the relative order value assigned to a collating element based on its order in the character collation sequence.
In the file
<b> are defined in this order:
This makes the relevant subsequence of collation sequence be
aAbB. This is what matters to
To confirm this I (temporarily) moved the following collation order entry
<U004B> <k>;<BAS>;<CAP>;IGNORE # 649 K
to a position just before the entry for
v, i.e. somewhere in between
z. I rebuilt my locales with
sort file | tr -d '\n' still returns
…iIjJkKlLmM… (the weights did not change, the collation sequence did not change), but
grep '[a-z]' file | tr -d '\n' yields:
It means I made
K belong to
[a-z] by changing the collation order.
If you want
grep '[a-z]' file | tr -d '\n' to return a permutation of
aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ rather than
abcdefghijklmnopqrstuvwxyz, then you need to use a locale with different collation order. It may be a custom locale.