Chci odstranit duplicitní řádky ze souboru se slovy syrského písma. Zdrojový soubor má 3 řádky, 1. a 3. jsou identické.
$ cat file.txt
ܐܒܘܢ
ܢܗܘܐ
ܐܒܘܢ
Když použiji sort
a uniq
, výsledek předpokládá, že všechny 3 řádky jsou identické, což je špatně:
$ cat file.txt | sort | uniq -c
3 ܐܒܘܢ
Nepomůže ani explicitní nastavení národního prostředí na syrštinu.
$ LC_COLLATE=syr_SY.utf8 cat file.txt | sort | uniq -c
3 ܐܒܘܢ
Proč by se to stalo?
Používám Kubuntu 18 a bash, pokud na tom záleží.
Přijatá odpověď:
GNU implementace uniq
jako na Ubuntu, s -c
, neuvádí počty sousedících identických řádky, ale počty souvislých řádků, které třídí stejně¹.
Většina mezinárodních lokalit na systémech GNU má tu chybu, že mnoho zcela nesouvisejících znaků bylo definováno se stejným pořadím řazení, protože jejich pořadí řazení není definováno vůbec. Většina ostatních OS zajišťuje, že všechny znaky mají odlišné pořadí řazení.
$ expr ܐ = ܒ
1
(expr
‘s =
operátor pro argumenty, které nejsou číselné, vrátí 1, pokud jsou operandy seřazeny stejně, jinak 0).
Totéž platí pro ar_SY.UTF-8
nebo en_GB.UTF-8
.
To, co byste potřebovali, je národní prostředí, kde bylo těmto postavám přiděleno jiné pořadí řazení. Pokud by Ubuntu mělo národní prostředí pro syrský jazyk, dalo by se očekávat, že těmto znakům bude přiřazeno jiné pořadí řazení, ale Ubuntu takové lokality nemá.
Můžete se podívat na výstup locale -a
pro seznam podporovaných lokalit. Další národní prostředí můžete povolit spuštěním dpkg-reconfigure locales
jako root
. Další národní prostředí můžete také definovat ručně pomocí localedef
na základě definičních souborů v /usr/share/i18n/locales
, ale nenajdete tam žádná data pro syrský jazyk.
Všimněte si, že v:
LC_COLLATE=syr_SY.utf8 cat file.txt | sort | uniq -c
Proměnnou LC_COLLATE nastavujete pouze pro cat
příkaz (který neovlivňuje způsob, jakým vydává obsah souboru, cat
nezajímá řazení ani kódování znaků, protože se nejedná o textový nástroj). Měli byste jej nastavit pro obě sort
a uniq
. Také byste měli nastavit LC_CTYPE
do národního prostředí, které má znakovou sadu UTF-8.
Protože váš systém nemá syr_SY.utf8
locale, to je stejné jako použití C
locale (výchozí národní prostředí).
Ve skutečnosti zde pravděpodobně chcete použít národní prostředí C nebo C.UTF-8.
V těchto národních prostředích je pořadí řazení založeno na bodu kódu, bodu kódu Unicode pro C.UTF-8, hodnotě bajtu pro C, ale nakonec je to stejné, jako má kódování znaků UTF-8 tuto vlastnost.
$ LC_ALL=C expr ܐ = ܒ
0
$ LC_ALL=C.UTF-8 expr ܐ = ܒ
0
Takže s:
(export LANG=ar_SY.UTF-8 LC_COLLATE=C.UTF-8 LANGUAGE=syr:ar:en
unset LC_ALL
sort <file | uniq -c)
Měli byste mít LC_CTYPE s UTF-8 jako znakovou sadu, pořadí řazení založené na bodu kódu a další nastavení relevantní pro váš region, takže například chybové zprávy v syrštině nebo arabštině, pokud GNU coreutils sort
nebo uniq
zprávy byly do těchto jazyků přeloženy (zatím nebyly).
Pokud vám na těch ostatních nezáleží jeho použití je stejně snadné (a také přenosnější):
<file LC_ALL=C sort | LC_ALL=C uniq -c
Nebo
(export LC_ALL=C; <file sort | uniq -c)
jak již @isaac ukázal.