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 -u
i 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
#
sort
sam (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 obusort
iuniq
utrata danych (w niektórych przypadkach).sort -u
iuniq
działa dobrze z:LC_COLLATE=C; echo -e "〼\n〇\n〇" |sort -u
(lub|uniq
)Odpowiedzi:
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. Funkcjastrxfrm
konstruuje tę kanoniczną formę.Zobaczmy kanoniczne formy kilku ciągów znaków (z GNU libc, pod ściśnięciem Debiana):
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-8
ustawień regionalnych. Są one jednak obecne w japońskich lokalizacjach.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 dlaU3007
aniU303C
nie 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
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.
źródło
charmaps/UTF-8
nie mówi nic o sortowaniu, tylko to się liczylocales/en_US
. Pierwsza zasadaLC_COLLATE
brzmi: nie używajLC_COLLATE
. W ustawieniach narodowych C (= POSIX) sortowanie jest rozsądne (oparte wyłącznie na wartościach liczbowych).LC_COLLATE=C
... dzięki ...Aby „bezpiecznie”
sort
napisy Unicode, może rzucić okiem namsort
:http://www.billposer.org/Software/msort.html
źródło
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 :)