Почему 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

Показывает, что на компьютере Debian Buster с локалью en_US.utf8 сортировка по столбцам (для отдельных символов) сначала имеет все знаки препинания, затем цифры, а затем смешанные регистры букв. То есть: aAbB, строчные и заглавные буквы вместе.

Предположим, что это верно и это именно то, чего пользователь (я) хочет от сопоставления.

Однако в той же системе, без каких-либо других изменений, происходит следующее:

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

То есть диапазон a-zпреобразуется чем-то только в строчные буквы ASCII.

Кто выполняет перевод и как его можно контролировать или изменять?

Я не спрашиваю о том, что такое строчные буквы или что должно означать [az] или что кто-то хочет, чтобы это означало.

Я полагаю, что [a-z]это диапазон, который начинается aи заканчиваетсяz в порядке сортировки.

Я понимаю, что некоторые другие пользователи хотят, чтобы это было [a-z]то же самое, что и "строчные" в любой локали. И я мог бы "жить с этим" по умолчанию.

Но как я могу это контролировать и/или менять, если это необходимо? Где ручка, чтобы это изменить?

Нет, изменение файлов сортировки не помогает, что-то находится за пределами этого и навязывает личное мнение, что a [a-z]должно означать ASCII-строчные символы всегда и во всех локациях.

решение1

Я прочитал то, чтоСостояния POSIX. Моя интерпретация такова: есть два неэквивалентных понятия:

  • последовательность сортировки (последовательность сортировки)
  • порядок сопоставления

Соответствующие фрагменты [выделено мной]:

Категория LC_COLLATEпредоставляетпоследовательность сортировкиопределение многочисленных утилит в томе «Оболочка и утилиты» POSIX.1-2017 ( ls, sort, и т. д.), сопоставление регулярных выражений (см. Регулярные выражения) и функции strcoll(), strxfrm(), wcscoll(), и wcsxfrm()в томе «Системные интерфейсы» POSIX.1-2017.

Апоследовательность сортировкиопределение должно определять относительный порядок между элементами сортировки (символами и многосимвольными элементами сортировки) в локали. Этот порядок выражается в терминах значений сортировки; то есть, назначая каждому элементу одно или несколько значений сортировки (также известных как веса сортировки). […]

Ключевое order_startслово должно предшествоватьпорядок сопоставлениязаписи, а также определить количество весов для этогопоследовательность сортировкиопределение и другие правила сопоставления.

Theпорядок сопоставлениякак определено в этом разделе, влияет на интерпретацию выражений в скобках в регулярных выражениях (см. Выражение в скобках RE).

Для sortсортировки важна последовательность, т. е. веса. Для grep '[a-z]'сортировки важен порядок, т. е. порядок записей порядка сортировки.

К сожалению, только последовательность сортировкиопределено явно, поэтому нет четких указаний на то, что порядок сортировки представляет собой иную концепцию.

Последовательность сортировки
Относительный порядок сортировки элементов, определяемый настройкой категории LC_COLLATEв текущей локали. Последовательность сортировки используется для сортировки и определяется из весов сортировки, назначенных каждому элементу сортировки. При отсутствии весов последовательность сортировки — это порядок, в котором сортировочные элементы указаны между order_startи order_endключевыми словами в LC_COLLATEкатегории.


В моем Debian 9, когда дело доходит до LC_COLLATE, многие локали в конечном итоге ссылаются на iso14651_t1_common(ie /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>) не находится между записями для aи z.

Все еще записи для aи Aуказывают тот же символ сортировки <a>. Аналогично bи Bуказывают <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, то вам нужно использовать локаль с другим порядком сортировки. Это может быть пользовательская локаль.

Связанный контент