Куда делась строка `uniq` или` sort -u` с некоторыми символами юникода?


10

Что происходит в следующем фрагменте кода? Я не получаю ожидаемый результат.

Я бы подумал, что это ошибка, но это происходит для 2 разных программ (uniq и sort), поэтому я подозреваю, что это как-то связано ... ну, я не знаю, что ... отсюда вопрос.

Первые 3 (из 4) примеров работают, но четвертый не помогает!

Я ожидал бы того же поведения для всех без исключения персонажей.
то есть. распечатать 2 строки (из 3 строк ввода) ... но в 4-м случае я получаю только 1 строку (для обоих sort -uи uniq); две одинаковые линии просто исчезают!

Я преобразовал вывод '\ n' в пространство для компактности вида.

Я использую uniq и сортирую из (GNU coreutils) 7.4 ... работающий на рабочем столе Ubuntu 10.04.3 LTS.

Сценарий:

{
  locale -k LC_COLLATE
  echo
  for c1 in x 〼 ;do 
    for c2 in z 〇 ;do 
      echo -n "asis   : "; echo -e "$c1\n$c2\n$c2"          |tr '\n' ' ';echo
      echo -n "uniq   : "; echo -e "$c1\n$c2\n$c2" |uniq    |tr '\n' ' ';echo
      echo -n "sort -u: "; echo -e "$c1\n$c2\n$c2" |sort -u |tr '\n' ' ';echo
      echo
    done
    echo
  done
}

Выход:

collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=2081
collate-codeset="UTF-8"

asis   : x z z 
uniq   : x z 
sort -u: x z 

asis   : x 〇 〇 
uniq   : x 〇 
sort -u: 〇 x 


asis   : 〼 z z 
uniq   : 〼 z 
sort -u: 〼 z 

asis   : 〼 〇 〇 
uniq   : 〼 
sort -u: 〼 

# In the last example (of 4) where did the '〇' go? .. U+3007 IDEOGRAPHIC NUMBER ZERO
#

Пожалуйста, обратите внимание .. Чтобы было ясно. sortв одиночку (без опции -u ) ... не сжимает символы .. Что входит, выходит ... Однако, как и ожидал Гиллес, объяснение "экзотических" символов Юникода, имеющих одинаковое каноническое значение , эти символы не сортируются, за исключением того, что они выводятся как несортированная группа FIFO в «верх» вывода сортировки ... Таким образом, здесь действительно есть две проблемы: 1. Символы сортируются не так, как могло бы быть «наивно». «ожидается», и 2. «уникальная» особенность обоих sortи uniqпотери данных (в некоторых случаях).
Peter.O

Обновление: как упомянуто Жилем (когда сортировка по конкретному языку не обязательна, и порядок символов подходит), sort -uи uniqотлично работает с: LC_COLLATE=C; echo -e "〼\n〇\n〇" |sort -u(или |uniq)
Peter.O

Ответы:


11

Короткая версия: сортировка не работает в утилитах командной строки.

Более длинная версия: основная функция для сравнения двух строк strcoll. Описание не очень полезно, но концептуальный метод работы состоит в том, чтобы преобразовать обе строки в каноническую форму, а затем сравнить две канонические формы. Функция strxfrmстроит эту каноническую форму.

Давайте рассмотрим канонические формы нескольких строк (с GNU libc, под Debian squeeze):

$ export LC_ALL=en_US.UTF-8
$ perl -C255 -MPOSIX -le 'print "$_ ", unpack("h*", strxfrm($_)) foreach @ARGV' b a A à 〼 〇
b d010801020
a c010801020
A c010801090
à 101010102c6b
〼 101010102c6b102c6b102c6b
〇 101010102c6b102c6b102c6b

Как видите, 〼 и 〇 имеют одинаковую каноническую форму. Я думаю, что это потому, что эти символы не упоминаются в таблицах сопоставления en_US.UTF-8локали. Они, однако, присутствуют в японском языке.

$ export LC_ALL=ja_JP.UTF-8
$ perl -C255 -MPOSIX -le 'print "$_ ", unpack("h*", strxfrm($_)) foreach @ARGV' 〼 〇 
〼 303030
〇 3c9b

Исходный код для данных локали (в Debian squeeze) находится в /usr/share/i18n/locales/en_USтом числе /usr/share/i18n/locales/iso14651_t1_common. В этом файле нет записи для U3007или U303C, и при этом они не включены ни в один диапазон, который я могу найти.

Я не знаком с правилами построения порядка сортировки , но насколько я понимаю, соответствующие формулировки

Символ UNDEFINED должен интерпретироваться как включающий в себя все значения набора кодированных символов, не указанные явно или с помощью символа многоточия. (…) Если не определен символ UNDEFINED, а текущий набор кодированных символов содержит символы, не указанные в этом разделе, утилита выдаст предупреждающее сообщение и поместит такие символы в конце порядка сопоставления символов.

Похоже, вместо этого Glibc игнорирует символы, которые не указаны. Я не знаю, есть ли недостаток в моем понимании спецификации POSIX, если я что-то пропустил в определении локали Glibc, или есть ошибка в компиляторе локали Glibc.


@Gilles: Спасибо за информативное и подробное объяснение .. Теперь это имеет некоторый смысл, но мне остается только подумать, как "безопасно" использовать сортировку ... Мне не нужна особенно "чувствительная к локали" сортировка, поэтому любые грубые сортировка будет делать ... Есть ли быстрый обходной путь для этого? ... и я постепенно научусь этому, но это не произойдет "в одночасье" ... например, мой / usr / share / i18n / charmaps / UTF-8 содержит ссылки на оба рассматриваемых символа , но нахождение в этом определении UTF-8 (?), кажется, не помогает ... О, хорошо, какова была бы жизнь без ее маленьких загадок. :) ...
Peter.O

1
@fred charmaps/UTF-8ничего не говорит о сопоставлении, это locales/en_USважно. Первое правило LC_COLLATE: не используйте LC_COLLATE. В языковом стандарте C (= POSIX) параметры сортировки являются разумными (строго на основе числовых значений символов).
Жиль "ТАК - перестань быть злым"

2
В сортировочных и уникальный аспект работы хорошо , когда предшествует LC_COLLATE=C... спасибо ...
Peter.O

1
Дело не в том, что сортировка не работает в утилитах, а в том, что локали glibc плохо спроектированы. Такое поведение (в настоящее время, но см. Austingroupbugs.net/view.php?id=1070 ) разрешено POSIX, но это неудачно и нежелательно.
Стефан

6

Чтобы "безопасно" использовать sortстроки Unicode, возможно, взгляните на msort:

[...] Msort обеспечивает большую гибкость при выборе ключевых полей, больше типов сравнения, возможность использовать правила сопоставления из разных локалей на разных ключах, возможность обрабатывать числа в незападных системах счисления и множество других отсутствующих опций в сортировке GNU и BSD. В то время как msort понимает Unicode, GNU sort и BSD не понимают. [...]

http://www.billposer.org/Software/msort.html


@til: Спасибо, что сообщили мне об этом msort. Опциональный графический интерфейс немного облегчает знакомство с тем, что предлагается. Возможность скопировать сгенерированную команду очень удобна ... И да, она сортирует символы Юникода, но (разве вы просто не любите эти "buts":) ... но у нее нет уникальной опции: (... как упоминалось в ссылке, которую вы разместили: Capabilities of GNU sort and BSD sort lacking in msort are the ability to merge files without sorting them (the --merge option) and the ability to emit only the first of an equal run (the --unique option)... Хотя сортировка работает :)
Peter.O
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.