sed が grep (および sed、awk) のロケール照合ファイルで定義されていることを実行しないのはなぜですか?

sed が grep (および sed、awk) のロケール照合ファイルで定義されていることを実行しないのはなぜですか?

すべての(印刷可能な)ASCII 文字を含むファイルを用意します。

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

これはソートできます (tr を使用して長い出力を 1 行に減らします)。

$ 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 がどのロケールでも「小文字」と同じ意味になることを望んでいる人もいると理解しています。そして、私はデフォルトで「それを受け入れる」かもしれません。

しかし、必要に応じて、それをどのように制御および/または変更できるでしょうか? 変更するためのノブはどこにありますか?

いいえ、照合ファイルを変更しても役に立ちません。それ以上の何かが、[a-z]すべてのロケールで a は常に ASCII 小文字を意味するという個人的な見解を強制します。

答え1

私は何を読みましたかPOSIXの状態私の解釈では、同等ではない概念が 2 つあります。

  • 照合順序(照合順序)
  • 照合順序

関連する断片[強調は筆者による]:

このLC_COLLATEカテゴリーでは、照合順序POSIX.1-2017 の Shell and Utilities ボリュームの多数のユーティリティ ( lssortなど)、正規表現マッチング (「正規表現」を参照)、およびPOSIX.1-2017 の System Interfaces ボリュームの 、strcoll()strxfrm()、関数wcscoll()の定義。wcsxfrm()

照合順序定義は、ロケール内の照合要素 (文字および複数文字の照合要素) 間の相対的な順序を定義します。この順序は照合値で表現されます。つまり、各要素に 1 つ以上の照合値 (照合重みとも呼ばれます) を割り当てることによって表現されます。[…]

キーワードorder_start照合順序エントリと重みの数も定義します照合順序定義およびその他の照合ルール。

照合順序このセクションで定義されているように、正規表現内の括弧式の解釈に影響します (RE Bracket Expression を参照)。

照合順序sort、つまり重みが重要です。grep '[a-z]'照合順序、つまり照合順序エントリの順序が重要です。

残念ながら、照合順序だけが明示的に定義されたしたがって、照合順序が異なる概念であるという明確な兆候はありません。

照合順序現在のロケールのカテゴリ
の設定によって決定される照合要素の相対的な順序。照合順序は並べ替えに使用され、各照合要素に割り当てられた照合重みから決定されます。重みがない場合、照合順序は、カテゴリ内のキーワード間LC_COLLATEで照合要素が指定される順序です。order_startorder_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]、含まれません。AA<U0041>az

と のエントリはaA同じ照合シンボル を指定します<a>。同様にb、 とBは を指定します<b>。これは重みに変換されます。

重みは、文字(ロケール定義で指定された形式のいずれか)、<collating-symbol>s、<collating-element>s、省略記号、または特殊記号で表されますIGNORE。単一の文字、<collating-symbol>またはは、<collating-element>文字内の相対的な位置を表します。照合順序文字や記号自体ではなく、文字や記号の重み付けを表す。したがって、重みに絶対値を割り当てるのではなく、文字の順序に基づいて照合要素に割り当てられた相対的な順序値を使用して特定の重みが表現される。照合順序

ファイルでは<a>、 と は<b>次の順序で定義されます。

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

これにより、関連する部分列は照合順序であることaAbB。これが にとって重要なことですsort


これを確認するために、私は(一時的に)次の照合順序エントリを移動しました

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

を のエントリの直前の位置、つまりとvの間に移動します。 でロケールを再構築しました。は引き続き返されます(重みは変更されず、照合順序も変更されません) が、次の結果が生成されます:azlocale-gensort file | tr -d '\n'…iIjJkKlLmM…grep '[a-z]' file | tr -d '\n'

Kabcdefghijklmnopqrstuvwxyz

照合順序を変更して、K属するようにしたということです。[a-z]

ではなくgrep '[a-z]' file | tr -d '\n'の順列を返す場合は、異なる照合順序のロケールを使用する必要があります。カスタム ロケールの場合もあります。aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZabcdefghijklmnopqrstuvwxyz

関連情報