Ki jan kalite Linux a klase kòd

Entwodiksyon

Li tout te kòmanse ak yon script kout ki te sipoze konbine enfòmasyon adrès E-mail anplwaye yo jwenn nan lis itilizatè lis adrès, ak pozisyon anplwaye yo jwenn nan baz done depatman HR. Tou de lis yo te ekspòte nan dosye tèks Unicode Utf-8 epi sove ak tèminezon liy Unix.

Kontni mail.txt

Иванов Андрей;[email protected]

Kontni buhg.txt

Иванова Алла;маляр
Ёлкина Элла;крановщица
Иванов Андрей;слесарь
Абаканов Михаил;маляр

Pou rantre, yo te klase dosye yo dapre lòd Unix la sòt epi soumèt bay opinyon pwogram Unix la rantre nan, ki san atann echwe ak yon erè:

$> sort buhg.txt > buhg.srt
$> sort mail.txt > mail.srt
$> join buhg.srt mail.srt > result
join: buhg.srt:4: is not sorted: Иванов Андрей;слесарь

Lè w gade rezilta klasman an ak je ou te montre ke, an jeneral, klasman an kòrèk, men nan ka konyensidans ti non gason ak fi, ti non fi yo vin anvan ti non gason yo:

$> sort buhg.txt
Абаканов Михаил;маляр
Ёлкина Элла;крановщица
Иванова Алла;маляр
Иванов Андрей;слесарь

Sanble yon pwoblèm klasman nan Unicode oswa tankou yon manifestasyon feminis nan algorithm klasman an. Premye a se, nan kou, plis posib.

Ann mete li pou kounye a rantre nan epi konsantre sou sòt. Ann eseye rezoud pwoblèm nan lè l sèvi avèk pike syantifik. Premyèman, ann chanje lokal la soti nan fr sou ru_RU. Pou sòt, li ta ase yo mete varyab anviwònman an LC_COLLATE, men nou pa pral pèdi tan nan vetiy:

$> LANG=ru_RU.UTF-8 sort buhg.txt
Абаканов Михаил;маляр
Ёлкина Элла;крановщица
Иванова Алла;маляр
Иванов Андрей;слесарь

Pa gen anyen ki chanje.

Ann eseye kode dosye yo nan yon kodaj yon sèl-octet:

$> iconv -f UTF-8 -t KOI8-R buhg.txt 
 | LANG=ru_RU.KOI8-R sort 
 | iconv -f KOI8-R -t UTF8

Ankò pa gen anyen ki chanje.

Pa gen anyen ou ka fè, ou pral oblije chèche yon solisyon sou entènèt la. Pa gen anyen dirèkteman sou ti non Ris, men gen kesyon sou lòt estrawòdinè klasman. Pou egzanp, isit la se yon pwoblèm: sòt unix trete karaktè '-' (tiret) kòm envizib. Nan ti bout tan, strings yo "ab", "aa", "ac" yo klase kòm "aa", "ab", "ac".

Repons lan estanda toupatou: sèvi ak lokal pwogramè a "C" epi w ap kontan. Ann eseye:

$> LANG=C sort buhg.txt
Ёлкина Элла;крановщица
Абаканов Михаил;маляр
Иванов Андрей;слесарь
Иванова Алла;адвокат

Gen yon bagay ki chanje. Ivanov yo te aliye nan lòd ki kòrèk la, byenke Yolkina te glise yon kote. Ann retounen nan pwoblèm orijinal la:

$> LANG=C sort buhg.txt > buhg.srt
$> LANG=C sort mail.txt > mail.srt
$> LANG=C join buhg.srt mail.srt > result

Li te travay san erè, jan entènèt la te pwomèt. Lè sa a malgre Yolkina nan premye liy lan.

Pwoblèm nan sanble rezoud, men jis nan ka, an n eseye yon lòt kodaj Ris - Windows CP1251:

$> iconv -f UTF-8 -t CP1251 buhg.txt 
 | LANG=ru_RU.CP1251 sort 
 | iconv -f CP1251 -t UTF8 

Rezilta klasman an, etranj ase, pral kowenside ak lokal la "C", ak tout egzanp lan, kòmsadwa, kouri san erè. Gen kèk kalite mistik.

Mwen pa renmen mistik nan pwogramasyon paske li anjeneral maske erè. Nou pral gen seryezman gade nan ki jan li fonksyone. sòt e ki sa li afekte? LC_COLLATE .

Nan fen mwen pral eseye reponn kesyon yo:

  • poukisa yo te klase ti non fi yo mal?
  • poukisa LANG=ru_RU.CP1251 te tounen ekivalan LANG=C
  • Poukisa sòt и rantre nan diferan lide sou lòd kòd yo klase
  • poukisa gen erè nan tout egzanp mwen yo?
  • finalman ki jan yo sòt strings nan gou ou

Klase nan Unicode

Premye arè a pral teknik rapò No 10 gen dwa Unicode algorithm kolasyon sou entènèt unicode.org. Rapò a gen anpil detay teknik, kidonk kite m 'bay yon rezime tou kout sou lide prensipal yo.

Regwoupman — "konpare" fisèl se baz nenpòt algorithm klasman. Algoritm yo tèt yo ka diferan ("ti wonn", "fusion", "vit"), men yo tout pral sèvi ak yon konparezon nan yon pè nan fisèl detèmine lòd nan kote yo parèt.

Triye strings nan lang natirèl se yon pwoblèm jistis konplèks. Menm nan kodaj ki pi senp yo yon sèl-octet, lòd lèt yo nan alfabè a, menm nan yon fason diferan de alfabè Latin angle a, pa pral kowenside ankò ak lòd la nan valè nimerik ak ki lèt sa yo kode. Se konsa, nan alfabè Alman lèt la Ö kanpe ant О и P, ak nan kodaj la CP850 li vin ant ÿ и Ü.

Ou ka eseye abstrè de yon kodaj espesifik epi konsidere lèt "ideyal" ki ranje nan kèk lòd, jan sa fè nan Unicode. Kodaj UTF8, UTF16 oswa yon sèl-byte KOI8-R (si yo bezwen yon seri limite nan Unicode) pral bay diferan reprezantasyon nimerik nan lèt, men refere a menm eleman yo nan tablo debaz la.

Li sanble ke menm si nou bati yon tab senbòl nan grafouyen, nou pa yo pral kapab bay yon lòd senbòl inivèsèl nan li. Nan diferan alfabè nasyonal ki itilize menm lèt yo, lòd lèt sa yo ka diferan. Pou egzanp, an franse Æ pral konsidere kòm yon ligature ak klase kòm yon fisèl AE. Nan Nòvejyen Æ pral yon lèt separe, ki sitiye apre Z. By wout la, nan adisyon a ligatures tankou Æ Gen lèt ki ekri ak plizyè senbòl. Se konsa, nan alfabè a Czech gen yon lèt Ch, ki kanpe ant H и I.

Anplis diferans nan alfabè, gen lòt tradisyon nasyonal ki enfliyanse klasman. An patikilye, kesyon an rive: nan ki lòd mo ki gen lèt majiskil ak miniskil ta dwe parèt nan diksyonè a? Yo ka afekte klasman tou lè yo sèvi ak mak ponktiyasyon yo. Nan lang panyòl, yo itilize yon mak kesyon envèse nan kòmansman yon fraz entèwogatif (Ou renmen mizik?). Nan ka sa a, li evidan ke fraz entèwogatif pa ta dwe gwoupe nan yon gwoup separe andeyò alfabè a, men ki jan yo klase liy ak lòt mak ponktiyasyon?

Mwen pa pral rete sou klasman fisèl nan lang trè diferan de sa yo Ewopeyen yo. Remake byen ke nan lang ki gen yon direksyon ekriti dwat-a-gòch oswa tèt-anba, karaktè nan liy yo gen plis chans estoke nan lòd lekti, e menm sistèm ekriti ki pa alfabè yo gen pwòp fason yo lòd liy karaktè pa karaktè. . Pou egzanp, yeroglif yo ka bay lòd pa style (Kle karaktè Chinwa) oswa pa pwononsyasyon. Pou m onèt, mwen pa gen okenn lide ki jan emoji yo ta dwe ranje, men ou ka vini ak yon bagay pou yo tou.

Baze sou karakteristik ki nan lis pi wo a, kondisyon debaz yo pou konpare fisèl ki baze sou tab Unicode yo te fòmile:

  • konparezon fisèl pa depann de pozisyon karaktè yo nan tablo kòd la;
  • sekans karaktè ki fòme yon sèl karaktè yo redwi nan fòm kanonik (A + sèk ki anlè a se menm jan ak Å);
  • Lè w konpare kòd, yo konsidere yon karaktè nan yon kontèks fisèl la epi, si sa nesesè, konbine avèk vwazen li yo nan yon inite konparezon (Ch an Tchekoslovaki) oswa divize an plizyè (Æ an franse);
  • tout karakteristik nasyonal yo (alfabè, majiskil/miniskil, ponktiyasyon, kalite ekriti yo) dwe konfigirasyon jiska plasman manyèl lòd la (emoji);
  • konparezon enpòtan pa sèlman pou klasman, men tou nan anpil lòt kote, pou egzanp pou presize ranje ranje (ranplase {A... z} nan frape);
  • konparezon a ta dwe fè san patipri byen vit.

Anplis de sa, otè rapò a te fòme pwopriyete konparezon ke devlopè algorithm pa ta dwe konte sou:

  • algorithm konparezon an pa ta dwe mande pou yon seri karaktè separe pou chak lang (lang Ris ak Ikrenyen pataje pifò karaktè sirilik);
  • konparezon an pa ta dwe konte sou lòd karaktè nan tablo Unicode;
  • pwa fisèl pa ta dwe yon atribi nan fisèl la, paske menm fisèl la nan diferan kontèks kiltirèl ka gen pwa diferan;
  • pwa ranje yo ka chanje lè fusion oswa divize (de x < y li pa swiv sa xz < yz);
  • diferan fisèl ki gen menm pwa yo konsidere kòm egal nan pwen de vi algorithm klasman an. Entwodwi lòd adisyonèl nan fisèl sa yo se posib, men li ka degrade pèfòmans;
  • Pandan klasman repete, ranje ki gen menm pwa yo ka chanje. Robuste se yon pwopriyete yon algorithm klasman espesifik, epi li pa yon pwopriyete yon algorithm konparezon fisèl (gade paragraf anvan an);
  • Règ klasman yo ka chanje sou tan kòm tradisyon kiltirèl rafine/chanje.

Li se tou make ke algorithm nan konparezon pa konnen anyen sou semantik yo nan fisèl yo te trete. Kidonk, fisèl ki fòme sèlman nan chif pa ta dwe konpare kòm nimewo, ak nan lis non angle atik la (Beatles, The).

Yo nan lòd yo satisfè tout kondisyon yo espesifye, yo pwopoze yon algorithm klasman tab milti-nivo (aktyèlman kat-nivo).

Précédemment, karaktè yo nan fisèl la redwi nan fòm kanonik ak gwoupe nan inite nan konparezon. Chak inite konparezon yo asiyen plizyè pwa ki koresponn ak plizyè nivo konparezon. Pwa inite konparezon yo se eleman ansanm òdone (nan ka sa a, nonm antye) ki ka konpare pou plis oswa mwens. Siyifikasyon espesyal IGNORE (0x0) vle di ke nan nivo konparezon korespondan inite sa a pa patisipe nan konparezon an. Konparezon nan fisèl ka repete plizyè fwa, lè l sèvi avèk pwa yo nan nivo korespondan yo. Nan chak nivo, pwa yo nan inite konparezon yo nan de ranje yo se sekans konpare youn ak lòt.

Nan diferan aplikasyon algorithm pou diferan tradisyon nasyonal, valè koyefisyan yo ka diferan, men estanda Unicode a gen ladan yon tablo debaz pwa - "Tablo eleman kolasyon Unicode defo" (DUCET). Mwen ta renmen sonje ke mete varyab la LC_COLLATE se aktyèlman yon endikasyon nan seleksyon an nan tab la pwa nan fonksyon an konparezon fisèl.

Koefisyan pondération DUCET ranje jan sa a:

  • nan premye nivo, tout lèt yo redwi a menm ka a, dyakritik yo jete, mak ponktiyasyon (se pa tout) yo inyore;
  • nan dezyèm nivo a, se sèlman dyakritik yo pran an kont;
  • nan twazyèm nivo a, sèlman ka pran an kont;
  • nan katriyèm nivo a, se sèlman mak ponktyasyon yo pran an kont.

Konparezon an fèt nan plizyè pas: premyèman, koyefisyan premye nivo yo konpare; si pwa yo kowenside, Lè sa a, yon konparezon repete ak pwa dezyèm nivo yo te pote soti; Lè sa a, petèt yon twazyèm ak yon katriyèm.

Konparezon an fini lè ranje yo genyen inite konparezon ak pwa diferan. Ranje ki gen pwa egal nan tout kat nivo yo konsidere kòm egal youn ak lòt.

Algorithm sa a (ak yon pakèt detay teknik adisyonèl) te bay non rapò No 10 - "Algorithm kolasyon Unicode" (ACU).

Sa a se kote konpòtman an klasman nan egzanp nou an vin yon ti kras pi klè. Li ta bon pou konpare li ak estanda Unicode.

Pou teste aplikasyon yo ACU gen yon espesyal tès la, lè l sèvi avèk dosye pwa, mete ann aplikasyon DUCET. Ou ka jwenn tout kalite bagay komik nan dosye balans lan. Pou egzanp, gen lòd la nan majong ak domino Ewopeyen an, osi byen ke lòd la nan kostim nan yon pil kat (senbòl 1F000 ak pi lwen). Kostim yo kat yo mete dapre règ yo nan pon - PCBT, ak kat yo nan kostim la yo nan sekans T, 2,3, XNUMX ... K.

Manyèlman tcheke ke ranje yo klase kòrèkteman dapre DUCET ta dwe byen fatigan, men, erezman pou nou, gen yon aplikasyon egzanplè nan bibliyotèk la pou travay ak Unicode - "Konpozan entènasyonal pou Unicode"(ICU).

Sou sit entènèt bibliyotèk sa a, devlope nan IBM, gen paj Demo, ki gen ladan paj algorithm konparezon fisèl. Nou antre nan liy tès nou yo ak paramèt default, epi gade, nou jwenn pafè klasman Ris.

Абаканов Михаил;маляр
Ёлкина Элла;крановщица
Иванов Андрей;слесарь
Иванова Алла;адвокат

By wout la, sit entènèt la ICU Ou ka jwenn yon klarifikasyon nan algorithm nan konparezon lè w ap trete mak ponktiyasyon. Nan egzanp FAQ kolasyon apòt ak tire yo inyore.

Unicode te ede nou, men chèche rezon pou konpòtman etranj sòt в Linux pral oblije ale yon lòt kote.

Klase nan glibc

View rapid nan kòd sous sèvis piblik yo sòt nan GNU Core Utils te montre ke nan sèvis piblik la tèt li, lokalizasyon desann nan enprime valè aktyèl la nan varyab la LC_COLLATE lè w ap kouri nan mòd debug:

$ sort --debug buhg.txt > buhg.srt
sort: using ‘en_US.UTF8’ sorting rules

Yo fè konparezon fisèl lè l sèvi avèk fonksyon estanda a strcoll, ki vle di tout bagay ki enteresan nan bibliyotèk la glib.

Sou wiki pwojè a glib dedye a konparezon fisèl yon paragraf. Soti nan paragraf sa a li ka konprann ke nan glib klasman baze sou yon algorithm deja konnen nou ACU (Algorithm kolasyon Unicode) ak/oswa nan yon estanda tou pre li ISO 14651 (Entènasyonal lòd fisèl ak konparezon). Konsènan dènye estanda a, li ta dwe remake ke sou sit la standards.iso.org ISO 14651 ofisyèlman deklare piblikman disponib, men lyen ki koresponn lan mennen nan yon paj ki pa egziste. Google retounen plizyè paj ak lyen ki mennen nan sit ofisyèl ki ofri yo achte yon kopi elektwonik nan estanda a pou yon santèn ero, men nan twazyèm oswa katriyèm paj rezilta rechèch la gen tou lyen dirèk nan PDF. An jeneral, estanda a se pratikman pa diferan de ACU, men li pi raz pou li paske li pa genyen egzanp klè sou karakteristik nasyonal klasman fisèl.

Enfòmasyon ki pi enteresan sou wiki te gen yon lyen pou tracker ensèk ak yon diskisyon sou aplikasyon an nan konparezon fisèl nan glib. Soti nan diskisyon an li ka aprann sa glib itilize yo konpare fisèl ISOtab pèsonèl Tablo modèl komen an (CTT), adrès ki ka jwenn nan aplikasyon an A estanda ISO 14651. Ant 2000 ak 2015 tablo sa a nan glib pa t 'gen yon antretyen e li te byen diferan (omwen deyò) ak vèsyon aktyèl la nan estanda a. Soti nan 2015 a 2018, adaptasyon nan nouvo vèsyon tab la te fèt, e kounye a, ou gen yon chans rankontre nan lavi reyèl yon nouvo vèsyon tab la (Santos 8), ak ansyen (Santos 7).

Kounye a ke nou gen tout enfòmasyon sou algorithm ak tab oksilyè, nou ka retounen nan pwoblèm orijinal la epi konprann ki jan yo kòrèkteman sòt fisèl nan lokal Ris la.

ISO 14651/14652

Kòd sous tablo nou enterese nan CTT sou pifò distribisyon Linux se nan katalòg la /usr/share/i18n/locales/. Tablo a li menm se nan dosye a iso14651_t1_common. Lè sa a, sa a se direktiv dosye a kopi iso14651_t1_common enkli nan dosye a iso14651_t1, ki, nan vire, enkli nan dosye nasyonal yo, ki gen ladan fr и ru_RU. Sou pifò distribisyon Linux tout fichye sous yo enkli nan enstalasyon debaz la, men si yo pa prezan, w ap oblije enstale yon pake adisyonèl nan distribisyon an.

Estrikti dosye iso14651_t1 ka sanble fò anpil verbose, ak règ ki pa evidan pou konstwi non, men si ou gade nan li, tout bagay se byen senp. Estrikti a dekri nan estanda a ISO 14652, yon kopi ki ka telechaje sou sit entènèt la open-std.org. Yon lòt deskripsyon fòma dosye a ka li nan spesifikasyon POSIX soti nan OpenGroup. Kòm yon altènativ a lekti estanda a, ou ka etidye kòd sous la nan fonksyon an kolate_li в glibc/locale/programs/ld-collate.c.

Estrikti dosye a sanble sa a:

Pa default, karaktè a itilize kòm yon karaktè chape, ak fen liy lan apre karaktè # a se yon kòmantè. Tou de senbòl yo ka redefini, ki se sa ki fè nan nouvo vèsyon an nan tablo a:

escape_char /
comment_char %

Fichye a ap genyen siy nan fòma a oswa (Ki kote x - chif egzadesimal). Sa a se reprezantasyon egzadesimal pwen kòd Unicode nan kodaj la UCS-4 (Utf-32). Tout lòt eleman nan parantèz ang (ki gen ladan , <2> ak tankou a) yo konsidere kòm konstan fisèl senp ki gen ti siyifikasyon andeyò kontèks.

Fisèl LC_COLLATE di nou ke pwochen kòmanse done yo ki dekri konparezon an nan fisèl.

Premyèman, yo espesifye non pou pwa yo nan tablo konparezon an ak non pou konbinezon senbòl yo. Anjeneral pale, de kalite non yo fè pati de antite diferan, men nan dosye aktyèl la yo melanje. Non pwa yo espesifye pa mo kle a kolasyon-senbòl (karaktè konparezon) paske lè y ap konpare, karaktè Unicode ki gen menm pwa yo pral konsidere kòm karaktè ekivalan.

Longè total seksyon an nan revizyon dosye aktyèl la se apeprè 900 liy. Mwen te rale egzanp nan plizyè kote pou montre abitrè non ak plizyè kalite sentaks.

LC_COLLATE

collating-symbol <RES-1>
collating-symbol <BLK>
collating-symbol <MIN>
collating-symbol <WIDE>
...
collating-symbol <ARABIC>
collating-symbol <ETHPC>
collating-symbol <OSMANYA>
...
collating-symbol <S1D000>..<S1D35F>
collating-symbol <SFFFF> % Guaranteed largest symbol value. Keep at end of this list
...
collating-element <U0413_0301> from "<U0413><U0301>"
collating-element <U0413_0341> from "<U0413><U0341>"

  • kolasyon-senbòl mòso bwa yon fisèl OSMANYA nan tablo non balans yo
  • kolasyon-senbòl .. anrejistre yon sekans non ki gen yon prefiks S ak sifiks nimerik egzadesimal soti nan 1D000 до 1D35F.
  • Ffff в kolasyon-senbòl sanble yon gwo nonb antye ki pa siyen an egzadesimal, men se jis yon non ki ta ka sanble
  • Non vle di pwen kòd nan kodaj UCS-4
  • kolasyon-eleman soti nan " " anrejistre yon nouvo non pou yon pè pwen Unicode.

Yon fwa yo defini non pwa yo, yo espesifye pwa aktyèl yo. Piske se sèlman relasyon ki pi gran pase mwens enpòtan an konparezon, pwa yo detèmine pa yon senp sekans non lis. Pwa "pi lejè" yo ki nan lis premye, Lè sa a, "pi lou" yo. Kite m fè w sonje ke chak karaktè Unicode yo bay kat pwa diferan. Isit la yo konbine nan yon sèl sekans òdone. Nan teyori, nenpòt non senbolik ta ka itilize nan nenpòt nan kat nivo yo, men kòmantè endike ke devlopè yo mantalman separe non nan nivo.

% Symbolic weight assignments

% Third-level weight assignments
<RES-1>
<BLK>
<MIN>
<WIDE>
...
% Second-level weight assignments
<BASE>
<LOWLINE> % COMBINING LOW LINE
<PSILI> % COMBINING COMMA ABOVE
<DASIA> % COMBINING REVERSED COMMA ABOVE
...
% First-level weight assignments
<S0009> % HORIZONTAL TABULATION 
<S000A> % LINE FEED
<S000B> % VERTICAL TABULATION
...
<S0434> % CYRILLIC SMALL LETTER DE
<S0501> % CYRILLIC SMALL LETTER KOMI DE
<S0452> % CYRILLIC SMALL LETTER DJE
<S0503> % CYRILLIC SMALL LETTER KOMI DJE
<S0453> % CYRILLIC SMALL LETTER GJE
<S0499> % CYRILLIC SMALL LETTER ZE WITH DESCENDER
<S0435> % CYRILLIC SMALL LETTER IE
<S04D7> % CYRILLIC SMALL LETTER IE WITH BREVE
<S0454> % CYRILLIC SMALL LETTER UKRAINIAN IE
<S0436> % CYRILLIC SMALL LETTER ZHE

Finalman, tab la pwa aktyèl la.

Seksyon pwa yo fèmen nan liy mo kle yo lòd_kòmanse и order_end. Opsyon siplemantè lòd_kòmanse detèmine nan ki direksyon ranje yo analize nan chak nivo konparezon. Anviwònman default la se pou pi devan. Kò seksyon an konsiste de liy ki gen kòd senbòl ak kat pwa li yo. Kòd karaktè a ka reprezante pa karaktè li menm, yon pwen kòd, oswa yon non senbolik defini deja. Pwa yo ka bay non senbolik, pwen kòd, oswa senbòl yo menm. Si yo itilize pwen kòd oswa karaktè, pwa yo se menm ak valè nimerik pwen kòd la (pozisyon nan tablo Unicode). Karaktè ki pa espesifye klèman (jan mwen konprann) yo konsidere kòm asiyen nan tablo a ak yon pwa prensipal ki matche ak pozisyon nan tablo Unicode la. Valè pwa espesyal INYORE vle di ke senbòl la inyore nan nivo apwopriye nan konparezon.

Pou demontre estrikti balans yo, mwen te chwazi twa fragman jistis evidan:

  • karaktè ki konplètman inyore
  • senbòl ki ekivalan a nimewo twa nan de premye nivo yo
  • nan konmansman an nan alfabè a sirilik, ki pa gen diakritik, ak Se poutèt sa se klase sitou pa nivo yo premye ak twazyèm.

order_start forward;forward;forward;forward,position
<U0000> IGNORE;IGNORE;IGNORE;IGNORE % NULL (in 6429)
<U0001> IGNORE;IGNORE;IGNORE;IGNORE % START OF HEADING (in 6429)
<U0002> IGNORE;IGNORE;IGNORE;IGNORE % START OF TEXT (in 6429)
...
<U0033> <S0033>;<BASE>;<MIN>;<U0033> % DIGIT THREE
<UFF13> <S0033>;<BASE>;<WIDE>;<UFF13> % FULLWIDTH DIGIT THREE
<U2476> <S0033>;<BASE>;<COMPAT>;<U2476> % PARENTHESIZED DIGIT THREE
<U248A> <S0033>;<BASE>;<COMPAT>;<U248A> % DIGIT THREE FULL STOP
<U1D7D1> <S0033>;<BASE>;<FONT>;<U1D7D1> % MATHEMATICAL BOLD DIGIT THREE
...
<U0430> <S0430>;<BASE>;<MIN>;<U0430> % CYRILLIC SMALL LETTER A
<U0410> <S0430>;<BASE>;<CAP>;<U0410> % CYRILLIC CAPITAL LETTER A
<U04D1> <S04D1>;<BASE>;<MIN>;<U04D1> % CYRILLIC SMALL LETTER A WITH BREVE
<U0430_0306> <S04D1>;<BASE>;<MIN>;<U04D1> % CYRILLIC SMALL LETTER A WITH BREVE
...
<U0431> <S0431>;<BASE>;<MIN>;<U0431> % CYRILLIC SMALL LETTER BE
<U0411> <S0431>;<BASE>;<CAP>;<U0411> % CYRILLIC CAPITAL LETTER BE
<U0432> <S0432>;<BASE>;<MIN>;<U0432> % CYRILLIC SMALL LETTER VE
<U0412> <S0432>;<BASE>;<CAP>;<U0412> % CYRILLIC CAPITAL LETTER VE
...
order_end

Koulye a, ou ka retounen nan klasman egzanp yo depi nan konmansman an nan atik la. Anbiskad la chita nan pati sa a nan tablo pwa yo:

<U0020> IGNORE;IGNORE;IGNORE;<U0020> % SPACE
<U0021> IGNORE;IGNORE;IGNORE;<U0021> % EXCLAMATION MARK
<U0022> IGNORE;IGNORE;IGNORE;<U0022> % QUOTATION MARK
...

Li ka wè ke nan tablo sa a mak ponktiyasyon nan tablo a ASCII (ki gen ladan espas) prèske toujou inyore lè w konpare strings. Sèl eksepsyon yo se liy ki matche ak nan tout bagay eksepte mak ponktiyasyon yo jwenn nan pozisyon matche. Liy ki soti nan egzanp mwen an (apre klasman) pou algorithm konparezon an sanble sa a:

АбакановМихаилмаляр
ЁлкинаЭллакрановщица
ИвановаАлламаляр
ИвановАндрейслесарь

Lè ou konsidere ke nan tablo a nan balans, lèt majiskil nan Ris vin apre lèt miniskil (nan twazyèm nivo a pi lou pase ), klasman an sanble absoliman kòrèk.

Lè w ap mete yon varyab LC_COLLATE=C se yon tab espesyal chaje ki espesifye yon konparezon byte-by-byte

static const uint32_t collseqwc[] =
{
  8, 1, 8, 0x0, 0xff,
  /* 1st-level table */
  6 * sizeof (uint32_t),
  /* 2nd-level table */
  7 * sizeof (uint32_t),
  /* 3rd-level table */
  L'x00', L'x01', L'x02', L'x03', L'x04', L'x05', L'x06', L'x07',
  L'x08', L'x09', L'x0a', L'x0b', L'x0c', L'x0d', L'x0e', L'x0f',

...
  L'xf8', L'xf9', L'xfa', L'xfb', L'xfc', L'xfd', L'xfe', L'xff'
};

Depi nan Unicode pwen kòd la Ё vini anvan A, fisèl yo klase kòmsadwa.

Tèks ak tab binè

Li evidan, konparezon fisèl se yon operasyon trè komen, ak analiz tab CTT byen yon pwosedi ki koute chè. Pou optimize aksè nan tab la, li konpile nan fòm binè ak lòd la lokaldef.

Ekip lokaldef aksepte kòm paramèt yon dosye ki gen yon tablo karakteristik nasyonal yo (opsyon -i), kote tout karaktè yo reprezante pa pwen Unicode, ak yon dosye korespondans ant pwen Unicode ak karaktè nan yon kodaj espesifik (opsyon -f). Kòm rezilta travay la, yo kreye dosye binè pou lokal la ak non ki espesifye nan dènye paramèt la.

glibc sipòte de fòma dosye binè: "tradisyonèl" ak "modèn".

Fòma tradisyonèl la vle di non lokal la se non sous-anyè nan /usr/lib/locale/. Sou-répertoire sa a sere fichye binè yo LC_COLLATE, LC_CTYPE, LC_TIME ak sou sa. File LC_IDANTIFICATION gen non fòmèl lokal la (ki ka diferan de non anyè a) ak kòmantè.

Fòma modèn nan enplike estoke tout lokal yo nan yon sèl achiv /usr/lib/locale/locale-archive, ki se trase nan memwa a vityèl nan tout pwosesis lè l sèvi avèk glib. Non lokal la nan fòma modèn nan sijè a kèk kanonizasyon - se sèlman nimewo ak lèt ​​ki redwi a miniskil ki rete nan non kodaj yo. Se konsa ru_RU.KOI8-R, yo pral sove kòm ru_RU.koi8r.

Fichye Antre yo chèche nan anyè aktyèl la, osi byen ke nan anyè /usr/share/i18n/locales/ и /usr/share/i18n/charmaps/ pou fichye yo CTT ak dosye kodaj, respektivman.

Pou egzanp, lòd la

localedef -i ru_RU -f MAC-CYRILLIC ru_RU.MAC-CYRILLIC

pral konpile dosye a /usr/share/i18n/locales/ru_RU lè l sèvi avèk dosye kodaj /usr/share/i18n/charmaps/MAC-CYRILLIC.gz epi sove rezilta a nan /usr/lib/locale/locale-archive anba non an ru_RU.maccyrillic

Si ou mete varyab la LANG = en_US.UTF-8 lè sa a glib pral chèche binè lokal yo nan sekans sa a nan dosye ak anyè:

/usr/lib/locale/locale-archive
/usr/lib/locale/en_US.UTF-8/
/usr/lib/locale/en_US/
/usr/lib/locale/enUTF-8/
/usr/lib/locale/en/

Si yon lokal fèt nan fòma tradisyonèl ak modèn, Lè sa a, priyorite yo bay youn nan modèn.

Ou ka wè lis lokal konpile ak kòmandman an lokalite -a.

Prepare tab konparezon ou a

Koulye a, ame ak konesans la, ou ka kreye pwòp tab konparezon fisèl ideyal ou. Tablo sa a ta dwe kòrèkteman konpare lèt Ris, ki gen ladan lèt la Ё, epi an menm tan an pran an kont mak ponktiyasyon an akò ak tablo a. ASCII.

Pwosesis la nan prepare pwòp tab klasman ou a konsiste de de etap: koreksyon tab la pwa ak konpile li nan fòm binè ak lòd la. lokaldef.

Nan lòd pou tab la konparezon yo dwe ajiste ak depans koreksyon minim, nan fòma a ISO 14652 Yo bay seksyon pou ajiste pwa yon tab ki egziste deja. Seksyon an kòmanse ak yon mo kle rekòmande-apre epi endike pozisyon apre ranplasman an fèt. Seksyon an fini ak liy lan rekòmande-fen. Si li nesesè pou korije plizyè seksyon nan tablo a, Lè sa a, yo kreye yon seksyon pou chak seksyon sa yo.

Mwen kopye nouvo vèsyon dosye yo iso14651_t1_common и ru_RU soti nan depo a glib nan anyè lakay mwen ~/.local/share/i18n/locales/ ak yon ti kras modifye seksyon an LC_COLLATE в ru_RU. Nouvo vèsyon dosye yo konplètman konpatib ak vèsyon mwen an glib. Si ou vle sèvi ak vèsyon ki pi gran nan dosye, w ap oblije chanje non senbolik yo ak plas kote ranplasman an kòmanse nan tablo a.

LC_COLLATE
% Copy the template from ISO/IEC 14651
copy "iso14651_t1"
reorder-after <U000D>
<U0020> <S0020>;<BASE>;<MIN>;<U0020> % SPACE
<U0021> <S0021>;<BASE>;<MIN>;<U0021> % EXCLAMATION MARK
<U0022> <S0022>;<BASE>;<MIN>;<U0022> % QUOTATION MARK
...
<U007D> <S007D>;<BASE>;<MIN>;<U007D> % RIGHT CURLY BRACKET
<U007E> <S007E>;<BASE>;<MIN>;<U007E> % TILDE
reorder-end
END LC_COLLATE

An reyalite, li ta nesesè pou chanje jaden yo nan LC_IDANTIFICATION pou yo montre lokal la ru_MY, men nan egzanp mwen an sa a pa te obligatwa, depi mwen eskli achiv la nan rechèch la pou lokal yo lokal-achiv.

Sa lokaldef te travay ak dosye nan katab mwen an atravè yon varyab I18NPATH Ou ka ajoute yon anyè adisyonèl pou fè rechèch pou fichye opinyon, epi yo ka espesifye anyè a pou konsève pou dosye binè kòm yon chemen ak koupe:

$> I18NPATH=~/.local/share/i18n localedef -i ru_RU -f UTF-8 ~/.local/lib/locale/ru_MY.UTF-8

POSIX sipoze ke nan JIS ou ka ekri chemen absoli nan anyè ak dosye lokal yo, kòmanse ak yon koupe pi devan, men glib в Linux tout chemen yo konte soti nan anyè debaz la, ki ka ranplase atravè yon varyab LOCPATH. Apre enstalasyon LOCPATH=~/.local/lib/locale/ tout dosye ki gen rapò ak lokalizasyon yo pral chèche sèlman nan katab mwen an. Achiv lokal ak seri varyab la LOCPATH inyore.

Isit la se tès la desizif:

$> LANG=ru_MY.UTF-8 LOCPATH=~/.local/lib/locale/ sort buhg.txt
Абаканов Михаил;маляр
Ёлкина Элла;крановщица
Иванов Андрей;слесарь
Иванова Алла;адвокат

Houra! Nou te fè li!

Gen kèk erè

Mwen te deja reponn kesyon yo sou klasman fisèl poze nan kòmansman an, men gen toujou yon koup nan kesyon sou erè - vizib ak envizib.

Ann retounen nan pwoblèm orijinal la.

Ak pwogram nan sòt ak pwogram rantre nan sèvi ak menm fonksyon konparezon fisèl soti nan glib. Ki jan sa te rive sa rantre nan te bay yon erè klasman sou ranje ki klase dapre lòd la sòt nan lokal en_US.UTF-8? Repons lan se senp: sòt konpare tout fisèl la, epi rantre nan konpare sèlman kle a, ki pa default se kòmansman fisèl la jiska premye karaktè espas blan an. Nan egzanp mwen an, sa te lakòz yon mesaj erè paske klasman premye mo yo nan liy yo pa matche ak klasman liy konplè yo.

Lokal "C" garanti ke nan strings klase yo pral ranje inisyal substrings yo jiska premye espas la, men sa a sèlman maske erè a. Li posib yo chwazi done (moun ki gen menm ti non yo, men diferan non) ki, san mesaj erè a, ta bay yon rezilta fizyon kòrèk. Si nou vle rantre nan Fizyon liy fichye pa non konplè, Lè sa a, fason ki kòrèk la ta dwe presize klèman separasyon jaden an ak sòt pa jaden an kle, epi yo pa pa liy la tout antye. Nan ka sa a, fizyon an ap kontinye kòrèkteman epi pa pral gen okenn erè nan nenpòt lokal:

$> sort -t ; -k 1 buhg.txt > buhg.srt
$> sort -t ; -k 1 mail.txt > mail.srt
$> join -t ; buhg.srt mail.srt > result

Egzekisyon avèk siksè nan kodaj CP1251 gen yon lòt erè. Reyalite a se ke nan tout distribisyon konnen m ' Linux pakè yo manke lokal konpile ru_RU.CP1251. Si lokal konpile a pa jwenn, lè sa a sòt an silans sèvi ak yon konparezon byte-by-byte, ki se sa nou obsève.

By wout la, gen yon lòt ti glitch ki gen rapò ak inaksesiblite nan lokal konpile. Ekip LOCPATH=/tmp lokal -a pral bay yon lis tout lokal ki nan lokal-achiv, men ak seri a varyab LOCPATH pou tout pwogram (ki gen ladan pi plis la lokal) lokal sa yo pap disponib.

$> LOCPATH=/tmp locale -a | grep en_US
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_COLLATE to default locale: No such file or directory
en_US
en_US.iso88591
en_US.iso885915
en_US.utf8

$> LC_COLLATE=en_US.UTF-8 sort --debug
sort: using ‘en_US.UTF-8’ sorting rules

$> LOCPATH=/tmp LC_COLLATE=en_US.UTF-8 sort --debug
sort: using simple byte comparison

Konklizyon

Si ou se yon pwogramè ki abitye panse ke fisèl yo se yon seri bytes, Lè sa a, chwa ou LC_COLLATE=C.

Si ou se yon lengwis oswa yon konpilatè diksyonè, Lè sa a, ou pi bon konpile nan lokal ou a.

Si ou se yon itilizatè senp, Lè sa a, ou jis bezwen jwenn itilize nan lefèt ke lòd la ls-yon rezilta fichye k ap kòmanse ak yon pwen melanje ak fichye k ap kòmanse ak yon lèt, epi Kòmandan minwi, ki sèvi ak pwòp fonksyon entèn li yo pou klase non, mete dosye ki kòmanse ak yon pwen nan kòmansman lis la.

Referans

Rapò No 10 Unicode algorithm kolasyon

Pwa karaktè nan unicode.org

ICU — aplikasyon yon bibliyotèk pou travay ak Unicode nan IBM.

Tès klasman lè l sèvi avèk ICU

Pwa karaktè nan ISO 14651

Deskripsyon fòma dosye a ak balans ISO 14652

Diskisyon sou konparezon fisèl nan glib

Sous: www.habr.com

Add nouvo kòmantè