Gdzie zniknęła moja linia `uniq` lub` sort -u`, z niektórymi znakami Unicode

10

Co się dzieje w poniższym fragmencie kodu? Nie otrzymuję oczekiwanej wydajności.

Myślałem, że to błąd, ale zdarza się to w przypadku 2 różnych programów (uniq i sort), więc podejrzewam, że ma to coś wspólnego z ... cóż, nie wiem z czym ... stąd pytanie.

Pierwsze 3 (z 4) przykładów działają, ale czwarty zawodzi!

Oczekiwałbym tego samego zachowania dla wszystkich postaci.
to znaczy. wydrukować 2 linie (z 3 linii wejściowych) ... ale w czwartym przypadku dostaję tylko 1 linię (dla obu sort -ui uniq); dwa identyczne linie po prostu znikają!

Przekształciłem wyjściowy „\ n” w przestrzeń, aby uzyskać zwartość widoku.

Używam uniq i sortuj według (GNU coreutils) 7.4 ... działającego na Ubuntu 10.04.3 LTS.

Scenariusz:

{
  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
}

Wyjście:

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
#
Peter.O
źródło
Uwaga .. Aby było całkiem jasne. sortsam (bez opcji -u ) ... nie pożera znaków ... Co wchodzi, wychodzi ... Jednak, jak można się spodziewać wyjaśnienia Gillesa „egzotycznych” znaków Unicode o tej samej wartości kanonicznej , te znaki nie są sortowane, poza tym, że są wyprowadzane jako nieposortowana grupa FIFO na „górę” wyników sortowania ... Tak więc są naprawdę dwa problemy: 1. Postacie nie są sortowane tak, jak mogłyby być „naiwnie” „oczekiwany” oraz 2. „Unikalna” funkcja obu sorti uniqutrata danych (w niektórych przypadkach).
Peter.O,
Aktualizacja: Jak wspomniał Gilles (gdy sortowanie specyficzne dla ustawień regionalnych nie jest konieczne, a kolejność znaków jest odpowiednia) sort -ui uniqdziała dobrze z: LC_COLLATE=C; echo -e "〼\n〇\n〇" |sort -u(lub |uniq)
Peter.O

Odpowiedzi:

11

Krótka wersja: sortowanie nie działa tak naprawdę w narzędziach wiersza poleceń.

Dłuższa wersja: podstawową funkcją do porównywania dwóch ciągów jest strcoll. Opis nie jest zbyt pomocny, ale koncepcyjna metoda działania polega na konwersji obu ciągów znaków na postać kanoniczną, a następnie porównaniu dwóch form kanonicznych. Funkcja strxfrmkonstruuje tę kanoniczną formę.

Zobaczmy kanoniczne formy kilku ciągów znaków (z GNU libc, pod ściśnięciem Debiana):

$ 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

Jak widać, 〼 i 〇 mają tę samą kanoniczną formę. Myślę, że dzieje się tak, ponieważ te znaki nie są wymienione w tabelach sortowania en_US.UTF-8ustawień regionalnych. Są one jednak obecne w japońskich lokalizacjach.

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

Kod źródłowy danych regionalnych (w squeeze Debiana) znajduje się w tym /usr/share/i18n/locales/en_US, co obejmuje /usr/share/i18n/locales/iso14651_t1_common. Ten plik nie ma pozycji dla U3007ani U303Cnie jest zawarty w żadnym zakresie, który mogę znaleźć.

Nie znam zasad budowania porządku sortowania , ale z tego, co rozumiem, odpowiednie sformułowanie jest

Symbol NIEZDEFINIOWANY należy interpretować jako obejmujący wszystkie wartości zestawu kodowanych znaków, które nie zostały wyraźnie określone lub za pomocą symbolu wielokropka. (…) Jeśli nie określono żadnego NIEZDEFINIOWANEGO symbolu, a bieżący kodowany zestaw znaków zawiera znaki nieokreślone w tej sekcji, narzędzie wydaje komunikat ostrzegawczy i umieszcza takie znaki na końcu kolejności sortowania znaków.

Wygląda na to, że Glibc ignoruje znaki, które nie zostały określone. Nie wiem, czy jest jakaś wada mojego rozumienia specyfikacji POSIX, czy coś przeoczyłem w definicji ustawień regionalnych Glibc, czy też jest błąd w kompilatorze ustawień regionalnych Glibc.

Gilles „SO- przestań być zły”
źródło
@Gilles: Dzięki za wyczerpujące i szczegółowe wyjaśnienia. Teraz ma to sens, ale zastanawiam się, jak „bezpiecznie” używać sortowania . Nie szukam szczególnie „wrażliwego na ustawienia regionalne”, więc wszelkie szorstkie sort zrobiłby ... Czy istnieje szybkie obejście tego problemu? ... i stopniowo to zrozumiem, ale nie stanie się to „z dnia na dzień” ... np. mój / usr / share / i18n / charmaps / UTF-8 zawiera odniesienia do obu omawianych postaci , ale bycie w tej definicji UTF-8 (?) nie pomaga ... No cóż, jak wyglądałoby życie bez jego małych tajemnic. :) ...
Peter.O
1
@fred charmaps/UTF-8nie mówi nic o sortowaniu, tylko to się liczy locales/en_US. Pierwsza zasada LC_COLLATEbrzmi: nie używaj LC_COLLATE. W ustawieniach narodowych C (= POSIX) sortowanie jest rozsądne (oparte wyłącznie na wartościach liczbowych).
Gilles „SO- przestań być zły”
2
Do sortowania i niepowtarzalny drobne prace aspekt gdy poprzedzone LC_COLLATE=C... dzięki ...
Peter.O
1
Nie chodzi o to, że sortowanie nie działa w narzędziach, ale że lokalizacje glibc są źle zaprojektowane. Takie zachowanie jest (obecnie, ale patrz austingroupbugs.net/view.php?id=1070 ) dozwolone przez POSIX, ale niefortunne i niepożądane.
Stéphane Chazelas
6

Aby „bezpiecznie” sortnapisy Unicode, może rzucić okiem na msort:

[...] Msort zapewnia większą elastyczność w wyborze pól kluczowych, więcej typów porównań, możliwość korzystania z reguł zestawiania z różnych lokalizacji na różnych kluczach, zdolność do obsługi liczb w systemach liczb innych niż zachodnie oraz wiele innych brakujących opcji w sortowaniu GNU i BSD. Podczas gdy msort rozumie Unicode, GNU sort i BSD sort nie. [...]

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

do
źródło
@til: Dzięki za poinformowanie mnie o tym msort. Opcjonalny interfejs GUI sprawia, że ​​wprowadzenie jest nieco łatwiejsze, aby zapoznać się z ofertą. Możliwość skopiowania wygenerowanego polecenia jest bardzo przydatna ... I tak, sortuje znaki Unicode, ale (nie lubisz tylko tych „ale”:) ... ale nie ma unikalnej opcji: (... jak wspomniano w linku, który opublikowałeś: 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)... Sortowanie działa jednak :)
Peter.O