為什麼 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]是一個開始a和結束的範圍z 按整理順序

我知道其他一些用戶希望[a-z]在任何區域設定中都具有與“小寫”相同的含義。預設情況下,我可能會「忍受這一點」。

但如果需要的話,我該如何控制和/或改變它?改變它的旋鈕在哪裡?

不,更改整理文件並沒有幫助,有些東西超出了這個範圍,並強制執行個人觀點,即[a-z]在所有語言環境中 a 必須始終表示 ASCII 小寫。

答案1

我讀了什麼POSIX 狀態。我的解釋是有兩個不等價的概念:

  • 整理序列(整理序列)
  • 整理順序

相關片段[強調我的]:

LC_COLLATE類別提供了整理順序POSIX.1-2017 的 Shell 和實用程式磁碟區中眾多實用程式的定義(lssort等)、正規表示式符合(請參閱正規表示式)以及POSIX.1-的系統介面磁碟區中的和strcoll()、、strxfrm()wcscoll()wcsxfrm()

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,那麼您需要使用具有不同排序順序的語言環境。它可能是自訂區域設定。

相關內容