Ievads
Viss sÄkÄs ar Ä«su skriptu, kas bija paredzÄts, lai apvienotu informÄciju par adresÄm e-pasts darbiniekiem, iegÅ«tiem no pasta sÅ«tÄ«jumu lietotÄju saraksta, ar darbinieku amatiem, iegÅ«tiem no personÄla datubÄzes. Abi saraksti tika eksportÄti teksta failos Unicode kodÄjumÄ UTF-8 un saglabÄti ar unix beigÄm rindÄm.
Saturs mail.txt
Ivanovs Andrejs;ia@example.comSaturs buhg.txt
Ivanova Alla;krÄvÄja
Jolkina Ella;krÄvÄja
Ivanovs Andrejs;metÄlists
Abakanovs Mihails;krÄvÄjaFaili tika kÄrtoti ar unix komandu kÄrtoÅ”ana un nodoti unix programmai join, kas negaidÄ«ti pabeidza darbu ar kļūdu:
$> sort buhg.txt > buhg.srt
$> sort mail.txt > mail.srt
$> join buhg.srt mail.srt > result
join: buhg.srt:4: nav kÄrtots: Ivanovs Andrejs;metÄlistsPÄrskatot kÄrtoÅ”anas rezultÄtu, acÄ«mredzami viss ir pareizi, taÄu gadÄ«jumos, kad ir atbilstoÅ”i vÄ«rieÅ”u un sievieÅ”u uzvÄrdi, sievietes ir pirms vÄ«rieÅ”iem:
$> sort buhg.txt
Abakanovs Mihails;krÄvÄja
Jolkina Ella;krÄvÄja
Ivanova Alla;krÄvÄja
Ivanovs Andrejs;metÄlistsIzskatÄs, ka tas ir sortÄÅ”anas kļūda Unicode vai feminisma izpausme sortÄÅ”anas algoritmÄ. Pirmais, protams, ir ticamÄks.
Atliksim to pagaidÄm join un koncentrÄsimies uz kÄrtoÅ”ana. MÄÄ£inÄsim atrisinÄt uzdevumu ar eksperimentÄlu pieeju. SÄksim ar vietÄjÄs iestatīŔanas maiÅu no en_US uz ru_RU. Lai kÄrtotu, pietiktu ar vides mainÄ«go iestatīŔanu LC_COLLATE, taÄu nesÄ«sim lietas lÄ«dz galam:
$> LANG=ru_RU.UTF-8 sort buhg.txt
Abakanovs Mihails;krÄvÄja
Jolkina Ella;krÄvÄja
Ivanova Alla;krÄvÄja
Ivanovs Andrejs;metÄlistsNekas nav mainÄ«jies.
MÄÄ£inÄsim pÄrcodinÄt failus vienbaitu kodÄjumÄ:
$> iconv -f UTF-8 -t KOI8-R buhg.txt
| LANG=ru_RU.KOI8-R sort
| iconv -f KOI8-R -t UTF8Atkal nekas nav mainījies.
Nekas cits neatliek, kÄ meklÄt risinÄjumu internetÄ. TieÅ”i par krievu uzvÄrdiem nav nekÄ, bet ir jautÄjumi par citÄm dÄ«vainÄ«bÄm sortÄÅ”anÄ. LÅ«k, piemÄram, Å”Äda problÄma: . ÄŖsi sakot, rindas "a-b", "aa", "ac" tiek kÄrtotas kÄ "aa", "a-b", "ac".
Atbilde visur ir standarta: izmantojiet programmÄtÄju vietÄjo iestatÄ«jumu "C" un jums bÅ«s laime. MÄÄ£inÄm:
$> LANG=C sort buhg.txt
Jolkina Ella;krÄvÄja
Abakanovs Mihails;krÄvÄja
Ivanovs Andrejs;metÄlists
Ivanova Alla;advokÄtsKaut kas ir mainÄ«jies. Ivanovi sakÄrtojÄs pareizÄ secÄ«bÄ, taÄu Jolkina kaut kur noslÄ«dÄja. Atgriežamies pie sÄkotnÄjÄ uzdevuma:
$> LANG=C sort buhg.txt > buhg.srt
$> LANG=C sort mail.txt > mail.srt
$> LANG=C join buhg.srt mail.srt > resultTas darbojÄs bez kļūdÄm, kÄ solÄ«jÄs internets. Un tas, neskatoties uz Jolkina pirmajÄ rindÄ.
ProblÄma, Ŕķiet, ir atrisinÄta, bet katrÄ ziÅÄ pamÄÄ£inÄsim vÄl vienu krievu kodÄjumu ā Windows kodÄjumu. CP1251:
$> iconv -f UTF-8 -t CP1251 buhg.txt
| LANG=ru_RU.CP1251 sort
| iconv -f CP1251 -t UTF8 SakÄrtojuma rezultÄts, kÄ nevis dÄ«vaini, sakritÄ«s ar lokÄlo iestatÄ«jumu. "C", un viss piemÄrs, attiecÄ«gi, iziet bez kļūdÄm. Kaut kas mistisks.
Es nemÄ«lu mistiku programmÄÅ”anÄ, jo parasti tÄ apgriež kļūdas. Man bÅ«s nopietni jÄpievÄrÅ”as jautÄjumam par to, kÄ tas darbojas. kÄrtoÅ”ana un uz ko tas ietekmÄ. LC_COLLATE .
BeigÄs es mÄÄ£inÄÅ”u atbildÄt uz jautÄjumiem:
- kÄpÄc nepareizi tika sakÄrtoti sievieÅ”u uzvÄrdi.
- kÄpÄc. LANG=ru_RU.CP1251 izrÄdÄ«jÄs ekvivalents. LANG=C.
- kÄpÄc kÄrtoÅ”ana un join atŔķirÄ«gi uzskati par sakÄrtoto rindu secÄ«bu.
- kÄpÄc visos manos piemÄros ir kļūdas.
- visbeidzot, kÄ sakÄrtot rindas pÄc savÄm vÄlmÄm.
SakÄrtoÅ”ana Unicode.
Pirmais apstÄklis bÅ«s tehniskÄ ziÅojuma Nr. 10 ar nosaukumu. vietnÄ . ZiÅojums satur daudz tehnisku detaļu, tÄdÄļ es atļauÅ”os sniegt Ä«su kopsavilkumu par pamata idejÄm.
SalÄ«dzinÄÅ”ana ā "salÄ«dzinÄÅ”ana" rindÄm ā ir jebkura sakÄrtoÅ”anas algoritma pamats. PaÅ”i algoritmi var atŔķirties ("burbuļa", "sadraudzÄ«bas", "ÄtrÄ"), bet tie visi izmantos salÄ«dzinÄjumu pÄri rindÄm, lai noteiktu viÅu secÄ«bu.
Rindu sakÄrtoÅ”ana dabiskajÄ valodÄ ir diezgan sarežģīts uzdevums. Pat visvienkÄrÅ”ÄkajÄs vienbaita kodÄÅ”anÄs gadÄ«jumos burti alfabÄtÄ, kas vismaz nedaudz atŔķiras no angļu alfabÄta, vairs nesakritÄ«s ar numuru secÄ«bu, ar kuriem Å”ie burti tiek kodÄti. TÄ vÄcu alfabÄtÄ burts Ć atrodas starp O un P, bet kodÄÅ”anÄ CP850 tas iekļūst starp Ćæ un Ć..
MÄÄ£inot abstrahÄties no konkrÄtÄs kodÄÅ”anas, var skatÄ«t "ideÄlos" burtus, kuri ir sakÄrtoti kÄdÄ secÄ«bÄ, kÄ tas veikts Unicode. KodÄjumi UTF8, UTF16 vai vienbaita KOI8-R (ja nepiecieÅ”ama ierobežota Unicode apakÅ”kopa) sniegs atŔķirÄ«gas numuriskas reprezentÄcijas burtiem, tomÄr atsauksies uz tiem paÅ”iem pamatvirsmas elementiem.
IzrÄdÄs, ka pat izveidojot simbolu tabulu no nulles, mÄs nevarÄsim noteikt universÄlo simbolu secÄ«bu. DažÄdÄs nacionÄlajÄs alfabÄtÄ, kas izmanto vienas un tÄs paÅ”as burtus, Å”o burtu secÄ«ba var atŔķirties. PiemÄram, franÄu valodÄ Ć tiks uzskatÄ«ta par ligatÅ«ru un tiks kÄrtojama kÄ virkne. AESavukÄrt norvÄÄ£u valodÄ Ć tiks uzskatÄ«ta par atseviŔķu burtu, kas atrodas pÄc Z. Starp citu, papildus ligatÅ«rÄm, piemÄram, Ć pastÄv burti, kuri tiek rakstÄ«ti ar vairÄkiem simboliem. TÄdÄjÄdi Äehu alfabÄtÄ ir burts Ch, kas atrodas starp H un I.
Papildus atŔķirÄ«bÄm alfabÄtÄ pastÄv arÄ« citas nacionÄlÄs tradÄ«cijas, kas ietekmÄ kÄrtoÅ”anu. Proti, rodas jautÄjums: kÄdÄ secÄ«bÄ vÄrdÄ, kas sastÄv no lielajiem un maziem burtiem, vajadzÄtu sekot vÄrdam vÄrdnÄ«cÄ? ArÄ« uz kÄrtoÅ”anu var ietekmÄt pieturzÄ«mju lietoÅ”anas Ä«patnÄ«bas. SpÄÅu valodÄ jautÄjuma teikuma sÄkumÄ tiek ielikts apgriezts jautÄjuma zÄ«me (ĀæTe gusta la mĆŗsica?). Å ajÄ gadÄ«jumÄ ir acÄ«mredzams, ka jautÄjuma teikumi nedrÄ«kst grupÄties atseviÅ”Ä·Ä klasterÄ« Ärpus alfabÄta, bet kÄ kÄrtot virknes ar citÄm pieturzÄ«mÄm?
Es nenodarbosÅ”os ar virkÅu kÄrtoÅ”anu valodÄs, kas stipri atŔķiras no eiropieÅ”u valodÄm. Izceļu, ka valodÄs ar rakstīŔanas virzienu no labÄs uz kreiso vai no augÅ”as uz leju simboli virkni, visticamÄk, tiek saglabÄti lasīŔanas secÄ«bÄ, un pat nealfabÄtiskajÄs rakstÄ«bÄs ir savi veidi, kÄ simbolus kÄrtot virknes. PiemÄram, hieroglifi var tikt kÄrtoti pÄc rakstÄ«bas () vai pÄc izrunas. KÄ jÄkÄrto emocijas, godÄ«gi sakot, es nevaru iedomÄties, bet arÄ« viÅiem var izdomÄt kÄdu risinÄjumu.
Balstoties uz iepriekÅ” minÄtajÄm iezÄ«mÄm, tika izstrÄdÄti galvenie prasÄ«bas virkÅu salÄ«dzinÄÅ”anai, pamatojoties uz Unicode tabulÄm:
- virkÅu salÄ«dzinÄÅ”ana nav atkarÄ«ga no simbolu pozÄ«cijas kodu tabulÄ;
- simbolu secÄ«bas, kas veido vienu simbolu, tiek nodotas kanoniskajÄ formÄ (A + augÅ”Äjais aplis ir tas pats, kas Ć );
- salÄ«dzinot virknes, simbols tiek aplÅ«kots virknes kontekstÄ un, ja nepiecieÅ”ams, tiek apvienots ar blakus esoÅ”ajiem simboliem vienÄ salÄ«dzinÄÅ”anas vienÄ«bÄ (Ch Äehu valodÄ) vai tiek sadalÄ«ts vairÄkos (Ć franÄu valodÄ);
- VisÄm nacionÄlajÄm Ä«patnÄ«bÄm (alfabets, lielie/mazie burti, pieturzÄ«mes, rakstÄ«bas veidu kÄrtÄ«ba) ir jÄbÅ«t iestatÄmÄm lÄ«dz pat manuÄlai kÄrtÄ«bas pieŔķirÅ”anai (emosmīļi);
- SalÄ«dzinÄÅ”ana ir svarÄ«ga ne tikai ŔķiroÅ”anai, bet arÄ« daudzÄs citÄs vietÄs, piemÄram, rindu diapazonu noteikÅ”anai (aizvietojot {A⦠Ń} ar bash);
- SalÄ«dzinÄÅ”anai jÄnotiek pietiekami Ätri.
TurklÄt ziÅojuma autori ir formulÄjuÅ”i salÄ«dzinÄÅ”anas Ä«paŔības, uz kurÄm algoritma izstrÄdÄtÄji nedrÄ«kst paļauties:
- SalÄ«dzinÄÅ”anas algoritmam nevajadzÄtu prasÄ«t atseviŔķu simbolu kopu katrai valodai (krievu un ukraiÅu valodas kopÄ«gi izmanto lielÄko daļu kirilicas simbolu);
- SalÄ«dzinÄÅ”ana nedrÄ«kst balstÄ«ties uz simbolu kÄrtÄ«bu Unicode tabulÄs;
- Rindas svars nedrÄ«kst bÅ«t rindas atribÅ«ts, jo viena un tÄ pati rinda dažÄdos kultÅ«ras kontekstos var iegÅ«t dažÄdus svarus;
- Rindu svari var mainÄ«ties apvienojot vai dalot (no x < y nenozÄ«mÄ, ka xz < yz);
- DažÄdas rindas, kurÄm ir vienÄdi svari, tiek uzskatÄ«tas par vienÄdÄm ŔķiroÅ”anas algoritma skatÄ«jumÄ. Papildu Å”Ädu rindu kÄrtÄ«bas ievieÅ”ana ir iespÄjama, taÄu tÄ var pasliktinÄt veiktspÄju;
- AtkÄrtotÄs ŔķiroÅ”anÄs laikÄ rindas, kurÄm ir vienÄdi svari, var mainÄ«t vietÄm. UzticamÄ«ba ir konkrÄta ŔķiroÅ”anas algoritma Ä«paŔība, bet ne rindu salÄ«dzinÄÅ”anas algoritma Ä«paŔība (sk. iepriekÅ”Äjo punktu);
- Å Ä·iroÅ”anas noteikumi var mainÄ«ties laika gaitÄ, kamÄr kultÅ«ras tradÄ«cijas tiek precizÄtas/vÄrtÄtas.
TÄpat ir noteikts, ka salÄ«dzinÄÅ”anas algoritmam nav nekÄdas zinÄÅ”anas par apstrÄdÄto rindu semantiku. TÄdÄjÄdi, rindas, kas sastÄv tikai no cipariem, nedrÄ«kst tikt salÄ«dzinÄtas kÄ skaitļi, un angļu nosaukumu sarakstos nedrÄ«kst izÅemt artikuli (Beatles, The).
Lai apmierinÄtu visus norÄdÄ«tos prasÄ«bas, tika piedÄvÄts daudzlÄ«meÅu (faktiski ÄetrlÄ«meÅu) tabulas ŔķiroÅ”anas algoritms.
IepriekÅ” simboli rindÄ tiek pÄrvÄrsti kanoniskÄ formÄ un grupÄti salÄ«dzinÄÅ”anas vienÄ«bÄs. Katrai salÄ«dzinÄÅ”anas vienÄ«bai tiek pieŔķirti vairÄki svari, kas atbilst vairÄkiem salÄ«dzinÄÅ”anas lÄ«meÅiem. SalÄ«dzinÄÅ”anas vienÄ«bu svari ir sakÄrtotas kopas elementi (Å”ajÄ gadÄ«jumÄ veseli skaitļi), kurus var salÄ«dzinÄt lielÄks-mazÄks. ÄŖpaÅ”Ä vÄrtÄ«ba IGNORED (0x0) nozÄ«mÄ, ka attiecÄ«gÄ salÄ«dzinÄjuma lÄ«menÄ« Ŕī viena nesanÄk salÄ«dzinÄÅ”anai. Rindas salÄ«dzinÄÅ”ana var atkÄrtoties vairÄkas reizes, izmantojot attiecÄ«go lÄ«meÅu svarus. Katram no lÄ«meÅiem divu rindu salÄ«dzinÄÅ”anas skalas secÄ«gi salÄ«dzina savÄ starpÄ.
DažÄdÄs algoritma implementÄcijÄs, Åemot vÄrÄ dažÄdas nacionÄlÄs tradÄ«cijas, koeficientu vÄrtÄ«bas var atŔķirties, taÄu Unicode standarta sastÄvÄ ietilpst pamata svaru tabula ā "NoklusÄjuma Unicode kolÄcijas elementu tabula" (DUCET). VÄlos atzÄ«mÄt, ka mainÄ«gÄ iestatīŔana LC_COLLATE faktiski ir norÄde uz svaru tabulas izvÄli rindas salÄ«dzinÄÅ”anas funkcijÄ.
Svara koeficienti DUCET ir veidoti Å”Ädi:
- pirmajÄ lÄ«menÄ« visas burti tiek pÄrvÄrsti vienÄ lietoÅ”anas režīmÄ, diakrÄ«tiskie zÄ«me tiek izslÄgti, pieturzÄ«mes (ne visas) tiek ignorÄtas;
- otrajÄ lÄ«menÄ« tiek Åemtas vÄrÄ tikai diakrÄ«tiskÄs zÄ«mes;
- treÅ”ajÄ lÄ«menÄ« tiek Åemts vÄrÄ tikai reÄ£istrs;
- ceturtajÄ lÄ«menÄ« tiek Åemti vÄrÄ tikai pieturzÄ«mes.
SalÄ«dzinÄÅ”ana notiek vairÄkos pÄrejos: vispirms tiek salÄ«dzinÄti pirmÄ lÄ«meÅa koeficienti; ja svari sakrÄ«t, tiek veikta atkÄrtota salÄ«dzinÄÅ”ana ar otrÄ lÄ«meÅa svariem; tad, iespÄjams, treÅ”ajÄ un ceturtajÄ.
SalÄ«dzinÄÅ”ana beidzas, kad rindÄs atrodas attiecÄ«gi viena otrai salÄ«dzinÄÅ”anas vienÄ«bas ar atŔķirÄ«giem svariem. Rindas, kurÄm ir vienÄdi svari visos Äetros lÄ«meÅos, tiek uzskatÄ«tas par lÄ«dzÄ«gÄm.
Å is algoritms (ar daudzÄm papildu tehniskÄm detaļÄm) deva nosaukumu pÄrskatam Nr. 10 ā "Unicode kolÄcijas algoritms" (UCA).
Å ajÄ vietÄ piemÄra ŔķiroÅ”anas uzvedÄ«ba kļūst nedaudz vieglÄk saprotama. BÅ«tu labi to salÄ«dzinÄt ar Unicode standartu.
Lai testÄtu implementÄcijas UCA ir pieejams speciÄls , kas izmanto , kas ievieÅ” DUCET. Svara failÄ var atrast dažÄdas zinÄmas lietas. PiemÄram, tur ir secÄ«ba mahjong kauliÅu un Eiropas domino, kÄ arÄ« kÄrÅ”u mastu secÄ«ba (simbols 1F000 un tÄlÄk). KÄrÅ”u masti tiek sakÄrtoti pÄc bridža noteikumiem ā PÄB, bet kartes masti ā secÄ«bÄ T, 2, 3⦠K.
Rokas pÄrbaudīŔana kÄrtoÅ”anas precizitÄti saskaÅÄ ar DUCET bÅ«tu diezgan nogurdinoÅ”a, taÄu, par laimi mums, ir izcila Unicode darbÄ«bas bibliotÄkas realizÄcija ā "" (ICU).
Å ajÄ bibliotÄkas vietnÄ, kas izstrÄdÄta IBM, ir demonstrÄcijas lapas, tostarp . IevadÄm mÅ«su testÄÅ”anas virknes ar noklusÄjuma iestatÄ«jumiem un, ak brÄ«nums, iegÅ«stam ideÄlu krievu ŔķiroÅ”anu.
Abakanovs Mihails;krÄsotÄjs
Jolkina Ella;krÄvÄjs
Ivanovs Andrejs;slÄdzis
Ivanova Alla;advokÄtsStarp citu, vietnÄ ICU var atrast precizÄjumu, kÄ darbojas virkÅu salÄ«dzinÄÅ”anas algoritms, apstrÄdÄjot interpunkcijas zÄ«mes. PiemÄros tiek ignorÄti apostrofi un defisi.
Unicode mums palÄ«dzÄja, bet meklÄt iemeslus dÄ«vainai uzvedÄ«bai kÄrtoÅ”ana par Linux bÅ«s jÄmeklÄ vÄl kaut kur citur.
Glasya ŔķiroŔana
ÄtrÄ avota koda apskate utilÄ«tÄ kÄrtoÅ”ana no GNU Core Utils parÄdÄ«ja, ka paÅ”Ä utilÄ«tÄ lokalizÄcija ir saistÄ«ta ar paÅ”reizÄjÄs mainÄ«gÄ vÄrtÄ«bas drukÄÅ”anu LC_COLLATE palaižot to atkļūdoÅ”anas režīmÄ:
$ sort --debug buhg.txt > buhg.srt
sort: izmanto āen_US.UTF8ā ŔķiroÅ”anas noteikumusVirkÅu salÄ«dzinÄÅ”ana tiek veikta ar standarta funkciju strcoll, tÄdÄjÄdi viss interesantais atrodas bibliotÄkÄ glibc.
Uz wiki projekta glibc virkÅu salÄ«dzinÄÅ”anai veltÄ«ts . No Ŕī paragrÄfa var saprast, ka glibc ŔķiroÅ”ana pamatojas uz mums jau zinÄmo algoritmu UCA (Unicode ŔķiroÅ”anas algoritms) un/vai uz tam tuvu standartu ISO 14651 (StarptautiskÄ virkÅu kÄrtoÅ”ana un salÄ«dzinÄÅ”ana). Par pÄdÄjo standartu jÄatzÄ«mÄ, ka vietnÄ ISO 14651 oficiÄli paziÅots par publiski pieejamu, bet attiecÄ«gÄ saite ved uz neeksistÄjoÅ”u lapu. Google sniedz vairÄkas lapas ar saitÄm uz oficiÄlajÄm vietnÄm, kas piedÄvÄ iegÄdÄties elektronisko kopiju par simtu eiro, bet treÅ”ajÄ-ÄeturtajÄ lapÄ meklÄÅ”anas rezultÄtÄ var atrast arÄ« tieÅ”Äs saites uz PDF. KopumÄ, standarts praktiski neatŔķiras no UCA, bet ir garlaicÄ«gÄk lasÄms, jo nesatur spilgtus piemÄrus par nacionÄlajÄm ŔķiroÅ”anas Ä«paŔībÄm.
InteresantÄkÄ informÄcija vietnÄ wiki izrÄdÄ«jÄs saite uz ar diskusijÄm par virkÅu salÄ«dzinÄÅ”anas Ä«stenoÅ”anu glibc. No diskusijas var uzzinÄt, ka glibc virkÅu salÄ«dzinÄÅ”anai tiek izmantota ISOtabula (CTT), kuras adresi var atrast standarta A pielikumÄ ISO 14651. Starp 2000. un 2015. gadu Ŕī tabula glibc nepiederÄja pie mÄ«tnes un diezgan ievÄrojami atŔķīrÄs (vismaz ÄrÄji) no paÅ”reizÄjÄs standarta versijas. No 2015. lÄ«dz 2018. gadam notika pielÄgoÅ”anÄs jaunajai tabulas versijai, un Å”obrÄ«d jums ir iespÄja sastapt gan jauno tabulas variantu (CentOS 8), gan veco (CentOS 7).
Tagad, kad mums ir visa informÄcija par algoritmu un palÄ«gtabulÄm, varam atgriezties pie sÄkotnÄjÄ jautÄjuma un saprast, kÄ pareizi sakÄrtot rindas krievu lokalizÄcijÄ.
ISO 14651/14652
InteresÄjoÅ”Äs tabulas avota kods CTT lielÄkajÄ daÄ¼Ä izplatÄ«jumu Linux atrodas katalogÄ /usr/share/i18n/locales/. Pati tabula atrodas failÄ iso14651_t1_common. PÄc tam Å”is fails ar direktÄ«vu copy iso14651_t1_common iekļaujas failÄ iso14651_t1, kas, savukÄrt, iekļaujas nacionÄlajos failos, tostarp en_US un ru_RU. LielÄkajÄ daÄ¼Ä izplatÄ«jumu Linux visi avota faili ir iekļauti pamata instalÄcijÄ, bet, ja to nav, tad bÅ«s jÄinstalÄ papildus pakotne no izplatÄ«juma.
Faila struktÅ«ra iso14651_t1 var Ŕķist drausmÄ«gi pÄrblÄ«vÄta, ar neiedomÄjamiem nosaukumu veidoÅ”anas likumiem, bet, ja izprot, tad viss ir diezgan vienkÄrÅ”i. StruktÅ«ra ir aprakstÄ«ta standarts ISO 14652, tÄ kopiju var lejupielÄdÄt no vietnes . VÄl vienu faila formÄta aprakstu var izlasÄ«t POSIX no OpenGroup. KÄ alternatÄ«va standarta lasīŔanai, varat izpÄtÄ«t funkcijas avota kodus collate_read par glibc/locale/programs/ld-collate.c.
Faila struktÅ«ra izskatÄs Å”Ädi:
NoklusÄjuma iestatÄ«jumos simbols tiek izmantots kÄ bÄgÅ”anas simbols, un rindiÅas beigas pÄc simbols # ir komentÄrs. Abus simbolus var pÄrrakstÄ«t, kas arÄ« tika izdarÄ«ts jaunajÄ tabulas versijÄ:
escape_char /
comment_char %FailÄ atradÄ«sies tokeni formÄtÄ <Uxxxx> vai <Uxxxxxxxx> (kur x ā seÅ”padsmito ciparu). TÄ ir seÅ”padsmito attÄloÅ”ana Unicode koda punktos kodÄjumÄ UCS-4 (UTF-32). Visi citi elementi stÅ«ros (ieskaitot <Uxxxx_xxxx>, <2> un tamlÄ«dzÄ«gi), tiek uzskatÄ«ti par vienkÄrÅ”Äm teksta konstantÄm, kurÄm nav Ä«paÅ”as nozÄ«mes Ärpus konteksta.
Rinda LC_COLLATE saka mums, ka turpmÄk sÄksies dati, kas apraksta rindas salÄ«dzinÄÅ”anu.
Vispirms tabulÄ salÄ«dzinÄÅ”anai tiek noteikti svaru nosaukumi un simbolu kombinÄciju nosaukumi. VispÄrÄ«gi runÄjot, divi nosaukumu veidi pieder divÄm dažÄdÄm entitÄtÄm, taÄu reÄlajÄ failÄ tie ir sajaukti. Svaru nosaukumi tiek norÄdÄ«ti ar atslÄgvÄrdu collating-symbol (salÄ«dzinoÅ”ais simbols), jo salÄ«dzinot Unicode simbolus, kam ir vienÄdi svari, tiks uzskatÄ«ti par ekvivalentiem simboliem.
KopÄjais sadaļas garums paÅ”reizÄjÄ faila revÄ«zijÄ ir apmÄram 900 rindu. Es ÅÄmu piemÄrus no vairÄkiem avotiem, lai parÄdÄ«tu nosaukumu nejauŔību un dažÄdus sintakses veidus.
LC_COLLATE
collating-symbol
collating-symbol
collating-symbol
collating-symbol
...
collating-symbol
collating-symbol
collating-symbol
...
collating-symbol ..
collating-symbol % GarantÄtais lielÄkais simbols. SaglabÄjiet Ŕīs saraksta beigÄs
...
collating-element no ""
collating-element no ""- collating-symbol reÄ£istrÄ rindu OSMANYA svaru nosaukumu tabulÄ
- collating-symbol .. reÄ£istrÄ nosaukumu secÄ«bu, kas sastÄv no prefiksa S un seÅ”padsmitskaitļa numura sufiksa no 1D000 lÄ«dz 1D35F.
- FFFF par collating-symbol izskatÄs kÄ liels bezzÄ«me skaitlis seÅ”padsmitskaitļu sistÄmÄ, bet <SFFFF> tas ir tikai nosaukums, kas varÄtu izskatÄ«ties kÄ <VERYBIGVAL>
- nosaukums <U0413> apzÄ«mÄ kodu punktu kodÄjumÄ UCS-4
- collating-element no "" reÄ£istrÄ jaunu nosaukumu Unicode punktu pÄrim.
Kad svaru nosaukumi ir noteikti, tiek noteikti paÅ”i svari. TÄ kÄ salÄ«dzinÄÅ”anÄ ir svarÄ«gas tikai attiecÄ«bas lielÄks-mazÄks, svari tiek noteikti ar vienkÄrÅ”u nosaukumu uzskaiti. Vispirms tiek uzskaitÄ«ti "vieglÄki" svari, pÄc tam "smagÄki". AtgÄdinu, ka katram Unicode simbolam ir pieŔķirti Äetri dažÄdi svari. Å eit tie ir apkopoti vienotÄ kÄrtotÄ secÄ«bÄ. TeorÄtiski, jebkuru simbolisku nosaukumu var izmantot jebkurÄ no Äetriem lÄ«meÅiem, bet komentÄri norÄda uz to, ka izstrÄdÄtÄji garÄ«gi sadala nosaukumus pa lÄ«meÅiem.
% SimboliskÄ svaru pieŔķirÅ”ana
% TreÅ”Ä lÄ«meÅa svaru pieŔķirÅ”ana
...
% OtrÄ lÄ«meÅa svaru pieŔķirÅ”ana
% KOMBINIJOÅ ANAS ZEME
% KOMBINIJOÅ ANAS KOMATS AUGÅ Ä
% KOMBINIJOÅ ANAS APGRIEZTS KOMATS AUGÅ Ä
...
% PirmÄ lÄ«meÅa svaru pieŔķirÅ”ana
% HORIZONTÄLÄ TABULÄCIJA
% RINDAS PÄRTRAUKÅ ANA
% VERTIKÄLÄ TABULÄCIJA
...
% KIRILICAS MAZA BURTA DE
% KIRILICAS MAZA BURTA KOMI DE
% KIRILICAS MAZA BURTA DJE
% KIRILICAS MAZA BURTA KOMI DJE
% KIRILICAS MAZA BURTA GJE
% KIRILICAS MAZA BURTA ZE AR LEJUZKÄRU
% KIRILICAS MAZA BURTA IE
% KIRILICAS MAZA BURTA IE AR BREVI
% KIRILICAS MAZA BURTA UKRAINAS IE
% KIRILICAS MAZA BURTA ZHEVisbeidzot, paÅ”Ä svaru tabula.
Svaru sekcija ir ietverta rindiÅÄs ar atslÄgvÄrdiem order_start un order_end. Papildu parametri order_start nosaka, kura virzienÄ rindiÅas tiek skatÄ«tas katrÄ salÄ«dzinÄjuma lÄ«menÄ«. NoklusÄjuma iestatÄ«jums ir parametrs forward. Sekcijas saturs sastÄv no rindiÅÄm, kas satur simbolu kodu un Äetrus tÄ svarus. Simbola kods var tikt attÄlots kÄ pats simbols, kodu punkts vai simboliskÄ nosaukuma, kas iepriekÅ” definÄts. Svarus var noteikt arÄ« simboliskie nosaukumi, kodu punkti vai paÅ”i simboli. Ja tiek izmantoti kodu punkti vai simboli, tad to svars atbilst kodu punkta skaitliskajai vÄrtÄ«bai (pozÄ«cija Unicode tabulÄ). Simboli, kas nav skaidri norÄdÄ«ti (cik es saprotu), tiek uzskatÄ«ti par pieskaitÄ«tiem tabulai ar primÄrÄs svara pozÄ«ciju, kas atbilst pozÄ«cijai Unicode tabulÄ. ÄŖpaÅ”a svara vÄrtÄ«ba IGNORE norÄda, ka attiecÄ«gajÄ salÄ«dzinÄjuma lÄ«menÄ« attiecÄ«gais simbols tiek ignorÄts.
Lai parÄdÄ«tu svaru struktÅ«ru, es izvÄlÄjos trÄ«s diezgan acÄ«mredzamus fragmentus:
- simboli, kas tiek pilnÄ«bÄ ignorÄti
- simboli, kas ir ekvivalentÄ«gi skaitlim trÄ«s pirmajos divos lÄ«meÅos
- kirilicÄ alfabÄta sÄkums, kas nesatur diakritiskÄs zÄ«mes, un tÄpÄc tiek Ŕķirots galvenokÄrt pÄc pirmÄ un treÅ”Ä lÄ«meÅa.
order_start forward;forward;forward;forward,position
IGNORE;IGNORE;IGNORE;IGNORE % NULL (in 6429)
IGNORE;IGNORE;IGNORE;IGNORE % START OF HEADING (in 6429)
IGNORE;IGNORE;IGNORE;IGNORE % START OF TEXT (in 6429)
...
;;; % DIGIT THREE
;;; % FULLWIDTH DIGIT THREE
;;; % PARENTHESIZED DIGIT THREE
;;; % DIGIT THREE FULL STOP
;;; % MATHEMATICAL BOLD DIGIT THREE
...
;;; % CYRILLIC SMALL LETTER A
;;; % CYRILLIC CAPITAL LETTER A
;;; % CYRILLIC SMALL LETTER A WITH BREVE
;;; % CYRILLIC SMALL LETTER A WITH BREVE
...
;;; % CYRILLIC SMALL LETTER BE
;;; % CYRILLIC CAPITAL LETTER BE
;;; % CYRILLIC SMALL LETTER VE
;;; % CYRILLIC CAPITAL LETTER VE
...
order_endTagad var atkal atgriezties pie piemÄru ŔķiroÅ”anas no raksta sÄkuma. Problema slÄpjas Å”ajÄ svaru tabulas daļÄ:
IGNORE;IGNORE;IGNORE; % SPACE
IGNORE;IGNORE;IGNORE; % EXCLAMATION MARK
IGNORE;IGNORE;IGNORE; % QUOTATION MARK
...Redzams, ka Å”ajÄ tabulÄ ir pieturzÄ«mes no tabulas. ASCII (ieskaitot atstarpi) salÄ«dzinot virknes, praktiski vienmÄr tiek ignorÄts. IzÅÄmums ir tikai virknÄm, kas sakrÄ«t pilnÄ«bÄ, izÅemot pieturzÄ«mes, kas atrodas sakrÄ«tajÄs pozÄ«cijÄs. Virknes no mana piemÄra (pÄc ŔķiroÅ”anas) algoritma salÄ«dzinÄÅ”anai izskatÄs Å”Ädi:
AbakanovsMihailsmÄkslinieks
EļkinaElakranovÄ
IvanovaAllamalÄrs
IvanovsAndrejsslÄdzisÅ emot vÄrÄ, ka svaru tabulÄ lielie burti krievu valodÄ seko maziem burtiem (treÅ”ajÄ lÄ«menÄ« <CAP> smagÄki nekÄ <MIN>), ŔķiroÅ”ana izskatÄs absolÅ«ti pareiza.
Iestatot mainÄ«go LC_COLLATE=C ielÄdÄjas Ä«paÅ”a tabula, kas nosaka baitu salÄ«dzinÄÅ”anu
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'fe', L'xff'
};TÄ kÄ Unicode koda punkts Š priekÅ”Ä A, tad virknes tiek Ŕķirotas attiecÄ«gi.
Teksta un binÄrÄs tabulas
AcÄ«mredzot virknu salÄ«dzinÄÅ”ana ir ÄrkÄrtÄ«gi bieži sastopama operÄcija, un tabulas analÄ«ze CTT ļoti dÄrga procedÅ«ra. Lai optimizÄtu piekļuvi tabulai, tÄ tiek kompilÄta binÄrÄ formÄ ar komandu localedef.
Komanda localedef pieÅemot kÄ parametrus failu ar nacionÄlo Ä«paŔību tabulu (poga -i), kurÄ visi simboli ir attÄloti ar Unicode punktiem, un failu ar Unicode punktu atbilstÄ«bÄm konkrÄtai kodÄÅ”anai (poga -f). DarbÄ«bas rezultÄtÄ tiek izveidoti binÄrie faili lokalizÄcijai ar nosaukumu, kas norÄdÄ«ts pÄdÄjÄ parametrÄ.
Glibc atbalsta divus binÄro failu formÄtus: "tradicionÄlais" un "mÅ«sdienu".
TradicionÄlais formÄts paredz, ka lokalizÄcijas nosaukums ir apakÅ”direktorijas nosaukums /usr/lib/locale/. Å ajÄ apakÅ”direktorijÄ tiek glabÄti binÄrie faili LC_COLLATE, LC_CTYPE, LC_TIME u.t.t. Fails LC_IDENTIFICATION satur oficiÄlo lokalizÄcijas nosaukumu (kas var atŔķirties no direktorijas nosaukuma) un komentÄrus.
MÅ«sdienu formÄts pieÅem, ka visas lokalizÄcijas tiek glabÄtas vienÄ arhÄ«vÄ /usr/lib/locale/locale-archive, kas tiek attÄlots virtuÄlajÄ atmiÅÄ visiem procesiem, kas to izmanto. glibcLokalizÄcijas nosaukums mÅ«sdienu formÄtÄ tiek pakļauts noteiktai kanonizÄcijai ā kodÄÅ”anas nosaukumos paliek tikai cipari un burti, kas pÄrveidoti par maziem burtiem. TÄ ru_RU.KOI8-R, tiks saglabÄts kÄ ru_RU.koi8r.
Izejfailus meklÄ paÅ”reizÄjÄ direktorijÄ, kÄ arÄ« direktorijÄs /usr/share/i18n/locales/ un /usr/share/i18n/charmaps/ failiem CTT un kodÄjumu failiem atbilstoÅ”i.
PiemÄram, komanda
localedef -i ru_RU -f MAC-CYRILLIC ru_RU.MAC-CYRILLICsastÄdÄ«s failu /usr/share/i18n/locales/ru_RU izmantojot kodÄÅ”anas failu /usr/share/i18n/charmaps/MAC-CYRILLIC.gz un saglabÄs rezultÄtu /usr/lib/locale/locale-archive ar nosaukumu ru_RU.maccyrillic
Ja iestatÄt mainÄ«go LANG=en_US.UTF-8 tad glibc tiks meklÄti binÄrie lokalizÄcijas faili Å”ÄdÄ secÄ«bÄ failu un direktoriju:
/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/Ja lokalizÄcija sastopama gan tradicionÄlajÄs, gan mÅ«sdienu formÄtÄ, tad prioritÄte tiek dota mÅ«sdienu formÄtam.
Sarakstu ar kompilÄtajÄm lokalizÄcijÄm var apskatÄ«t ar komandu locale -a.
Savas salÄ«dzinÄÅ”anas tabulas sagatavoÅ”ana
Tagad, apbruÅojoties ar zinÄÅ”anÄm, var izveidot savu ideÄlo salÄ«dzinÄÅ”anas tabulu. Å ai tabulai jÄspÄj pareizi salÄ«dzinÄt krievu burtus, tostarp burtu Š, un Åemt vÄrÄ interpunkcijas zÄ«mes saskaÅÄ ar tabulu ASCII.
Sava salÄ«dzinÄÅ”anas tabulas sagatavoÅ”anas procesÄ ir divi soļi: svara tabulas rediÄ£ÄÅ”ana un tÄs kompilÄÅ”ana binÄrÄ formÄ ar komandu localedef.
Lai salÄ«dzinÄÅ”anas tabulu varÄtu pielÄgot ar minimÄlÄm rediÄ£ÄÅ”anas izmaksÄm, tai jÄbÅ«t formÄtÄ ISO 14652 ir ir paredzÄtas svaru korekcijas sadaļas esoÅ”ajÄ tabulÄ. Sadaļa sÄkas ar atslÄgvÄrdu reorder-after un pozÄ«cijas norÄdīŔanu, pÄc kuras tiek veiktas nomaiÅas. Sadaļu noslÄdz rinda reorder-end. Ja ir nepiecieÅ”ams labot vairÄkas tabulas sadaļas, tad tiek izveidota pa sadaļai katram Å”Ädam fragmentam.
Es esmu nokopÄjis jaunÄs failu versijas iso14651_t1_common un ru_RU no krÄtuves glibc savam mÄjas katalogam ~/.local/share/i18n/locales/ un nedaudz rediÄ£Äjis sadaļu LC_COLLATE par ru_RU. JaunÄs failu versijas pilnÄ«bÄ saderÄ«gas ar manu versiju glibc. Ja vÄlaties izmantot vecÄs failu versijas, jums bÅ«s jÄmaina simboliskie nosaukumi un vieta, no kuras sÄkas nomaiÅa tabulÄ.
LC_COLLATE
% KopÄjiet veidni no ISO/IEC 14651
copy "iso14651_t1"
reorder-after
;;; % SPACE
;;; % EXCLAMATION MARK
;;; % QUOTATION MARK
...
;;; % RIGHT CURLY BRACKET
;;; % TILDE
reorder-end
END LC_COLLATEPatiesÄ«bÄ vajadzÄja nomainÄ«t laukus LC_IDENTIFICATION tÄ, lai tie norÄdÄ«tu uz lokalitÄti ru_MY, bet manÄ piemÄrÄ tas nebija nepiecieÅ”ams, jo es izslÄdzu lokalitÄÅ”u arhÄ«vu locale-archive.
Lai localedef strÄdÄja ar failiem manÄ mapÄ caur mainÄ«go I18NPATH var pievienot papildu katalogu ievades failu meklÄÅ”anai, bet katalogu binÄro failu saglabÄÅ”anai var norÄdÄ«t kÄ ceļu ar slÄ«psvÄ«trÄm:
$> I18NPATH=~/.local/share/i18n localedef -i ru_RU -f UTF-8 ~/.local/lib/locale/ru_MY.UTF-8POSIX pieÅem, ka LANG var rakstÄ«t absolÅ«tus ceļus uz katalogiem ar lokalitÄtÄm, kas sÄkas ar slÄ«psvÄ«tru, bet glibc par Linux visus ceļus uzskata no bÄzes kataloga, kuru var pÄrdefinÄt caur mainÄ«go LOCPATH. PÄc mainÄ«gÄ iestatīŔanas LOCPATH=~/.local/lib/locale/ visi faili, kas saistÄ«ti ar lokalizÄciju, tiks meklÄti tikai manÄ mapÄ. ArhÄ«vs ar lokalitÄtÄm pie iestatÄ«ta mainÄ«gÄ LOCPATH tiek ignorÄts.
Šis ir izŔķiroŔais tests:
$> LANG=ru_MY.UTF-8 LOCPATH=~/.local/lib/locale/ sort buhg.txt
Abakanovs Mihails;krÄsotÄjs
Jolkina Ella;krÄnu operators
Ivanovs Andrejs;metinÄtÄjs
Ivanova Alla;advokÄtsJÄ! MÄs to izdarÄ«jÄm!
Darbs pie kļūdÄm
Es jau atbildÄju uz jautÄjumiem par rindu kÄrtoÅ”anu, kas tika uzdoti sÄkumÄ, bet vÄl palikuÅ”as pÄris jautÄjumu par kļūdÄm ā redzamÄm un neredzamÄm.
AtgriezÄ«simies pie sÄkotnÄjÄ uzdevuma.
Un programma kÄrtoÅ”ana un programma join izmanto tÄs paÅ”as virkÅu salÄ«dzinÄÅ”anas funkcijas no glibc. KÄ tÄ varÄja sanÄkt, join izvadÄ«ja kÄrtoÅ”anas kļūdu par rindiÅÄm, kuras kÄrtoja komanda kÄrtoÅ”ana lokalizÄcijÄ en_US.UTF-8? ŠŃŠ²ŠµŃ ŠæŃŠ¾ŃŃ: kÄrtoÅ”ana salÄ«dzina rindiÅu kopumÄ, bet join salÄ«dzina tikai atslÄgu, kas pÄc noklusÄjuma ir rindiÅas sÄkums lÄ«dz pirmajam atstarpei. Manu piemÄrÄ tas noveda pie kļūdas ziÅojuma, jo pirmo vÄrdu kÄrtoÅ”ana rindiÅÄs nesakrita ar visu rindu kÄrtoÅ”anu.
LokalizÄcija "C" garantÄ, ka kÄrtojoÅ”ajÄs rindiÅÄs sÄkuma apakÅ”rindas lÄ«dz pirmajam atstarpei arÄ« bÅ«s sakÄrtotas, taÄu tas tikai slÄpj kļūdu. Ir iespÄjams izvÄlÄties tÄdus datus (cilvÄki ar vienÄdiem uzvÄrdiem, bet atŔķirÄ«giem vÄrdiem), kuri bez kļūdas ziÅojuma sniegtu nepareizu rezultÄtu failu apvienoÅ”anÄ. Ja mÄs vÄlamies, lai join apvienotu failu rindiÅas pÄc vÄrda un uzvÄrda, tad pareizÄ pieeja bÅ«s skaidri norÄdÄ«t lauku atdalÄ«tÄju un kÄrtoÅ”anu pÄc atslÄgas lauka, nevis pÄc visas rindiÅas. Å ÄdÄ gadÄ«jumÄ gan apvienoÅ”ana notiks pareizi, un nekur lokÄlÄ nebÅ«s kļūdu:
$> sort -t ; -k 1 buhg.txt > buhg.srt
$> sort -t ; -k 1 mail.txt > mail.srt
$> join -t ; buhg.srt mail.srt > resultVeiksmÄ«gi izpildÄ«ts piemÄrs kodÄjumÄ CP1251 satur vÄl vienu kļūdu. Proti, ka visÄs zinÄmÄs izplatÄ«jumos Linux paku trÅ«kst kompilÄtas lokalizÄcijas ru_RU.CP1251. Ja kompilÄtÄ lokalizÄcija netiek atrasta, tad kÄrtoÅ”ana klusi izmanto baitu salÄ«dzinÄjumu, ko arÄ« novÄrojÄm.
Starp citu, ir vÄl viena neliela kļūda, kas saistÄ«ta ar kompilÄtu lokalizÄciju nepieejamÄ«bu. Komanda LOCPATH=/tmp locale -a izsniegs visu lokalizÄciju sarakstu locale-archive, bet, ja ir iestatÄ«ta mainÄ«gÄ LOCPATH visÄm programmÄm (tostarp arÄ« paÅ”a locale) Ŕīs lokalizÄcijas bÅ«s nepieejamas.
$> 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 comparisonSecinÄjums
Ja tu esi programmÄtÄjs, kurÅ” pieradis domÄt, ka rindiÅas ir baitu kopums, tad tavs izvÄle LC_COLLATE=C.
Ja tu esi lingvists vai vÄrdnÄ«cu sastÄdÄ«tÄjs, tad tev labÄk bÅ«tu kompilÄt savu lokalizÄciju.
Ja tu esi parasts lietotÄjs, tad tev pietiks pierast pie tÄ, ka komanda ls -a izsniedz failus, kas sÄkas ar punktu, kopÄ ar failiem, kas sÄkas ar burtu, un Midnight Commander, kas izmanto savas iekÅ”ÄjÄs funkcijas, lai sakÄrtotu nosaukumus, izceļ failus, kas sÄkas ar punktu, saraksta sÄkumÄ.
Saites
Avots: habr.com
