Jinsi Linux inavyopanga mifuatano

Utangulizi

Yote ilianza na hati fupi ambayo ilipaswa kuchanganya habari ya anwani e-mail wafanyikazi waliopatikana kutoka kwa orodha ya watumiaji wa orodha ya barua, na nafasi za wafanyikazi zilizopatikana kutoka kwa hifadhidata ya idara ya Utumishi. Orodha zote mbili zilisafirishwa kwa faili za maandishi za Unicode UTF-8 na kuhifadhiwa na miisho ya mstari wa Unix.

Yaliyomo mail.txt

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

Yaliyomo buhg.txt

Иванова Алла;маляр
Ёлкина Π­Π»Π»Π°;ΠΊΡ€Π°Π½ΠΎΠ²Ρ‰ΠΈΡ†Π°
Иванов АндрСй;ΡΠ»Π΅ΡΠ°Ρ€ΡŒ
Абаканов ΠœΠΈΡ…Π°ΠΈΠ»;маляр

Ili kuunganisha, faili zilipangwa kwa amri ya Unix aina na kuwasilishwa kwa ingizo la programu ya Unix kujiunga na, ambayo imeshindwa bila kutarajia na hitilafu:

$> sort buhg.txt > buhg.srt
$> sort mail.txt > mail.srt
$> join buhg.srt mail.srt > result
join: buhg.srt:4: is not sorted: Иванов АндрСй;ΡΠ»Π΅ΡΠ°Ρ€ΡŒ

Kuangalia matokeo ya upangaji kwa macho yako ilionyesha kuwa, kwa ujumla, upangaji ni sawa, lakini katika kesi ya bahati mbaya ya majina ya kiume na ya kike, wale wa kike huja mbele ya wanaume:

$> sort buhg.txt
Абаканов ΠœΠΈΡ…Π°ΠΈΠ»;маляр
Ёлкина Π­Π»Π»Π°;ΠΊΡ€Π°Π½ΠΎΠ²Ρ‰ΠΈΡ†Π°
Иванова Алла;маляр
Иванов АндрСй;ΡΠ»Π΅ΡΠ°Ρ€ΡŒ

Inaonekana kama hitilafu ya kupanga katika Unicode au kama dhihirisho la ufeministi katika kanuni ya kupanga. Ya kwanza ni, bila shaka, inakubalika zaidi.

Hebu tuiahirishe kwa sasa kujiunga na na kuzingatia aina. Wacha tujaribu kusuluhisha shida kwa kutumia poking ya kisayansi. Kwanza, hebu tubadilishe eneo kutoka en_US juu ya ru_RU. Ili kupanga, itakuwa ya kutosha kuweka utofauti wa mazingira LC_COLLATE, lakini hatutapoteza muda kwa vitapeli:

$> LANG=ru_RU.UTF-8 sort buhg.txt
Абаканов ΠœΠΈΡ…Π°ΠΈΠ»;маляр
Ёлкина Π­Π»Π»Π°;ΠΊΡ€Π°Π½ΠΎΠ²Ρ‰ΠΈΡ†Π°
Иванова Алла;маляр
Иванов АндрСй;ΡΠ»Π΅ΡΠ°Ρ€ΡŒ

Hakuna kilichobadilika.

Wacha tujaribu kurekebisha faili kuwa usimbaji wa baiti moja:

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

Tena hakuna kilichobadilika.

Hakuna unachoweza kufanya, itabidi utafute suluhisho kwenye Mtandao. Hakuna kitu moja kwa moja juu ya majina ya Kirusi, lakini kuna maswali juu ya aina zingine za upangaji. Kwa mfano, hapa kuna shida: unix sort hushughulikia herufi '-' (dashi) kama zisizoonekana. Kwa kifupi, masharti "ab", "aa", "ac" yamepangwa kama "aa", "ab", "ac".

Jibu ni la kawaida kila mahali: tumia eneo la programu "C" na utakuwa na furaha. Tujaribu:

$> LANG=C sort buhg.txt
Ёлкина Π­Π»Π»Π°;ΠΊΡ€Π°Π½ΠΎΠ²Ρ‰ΠΈΡ†Π°
Абаканов ΠœΠΈΡ…Π°ΠΈΠ»;маляр
Иванов АндрСй;ΡΠ»Π΅ΡΠ°Ρ€ΡŒ
Иванова Алла;Π°Π΄Π²ΠΎΠΊΠ°Ρ‚

Kitu kimebadilika. Ivanovs walijipanga kwa mpangilio sahihi, ingawa Yolkina aliteleza mahali pengine. Wacha turudi kwenye shida ya asili:

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

Ilifanya kazi bila makosa, kama Mtandao ulivyoahidi. Na hii licha ya Yolkina kwenye safu ya kwanza.

Tatizo linaonekana kutatuliwa, lakini ikiwa tu, hebu tujaribu encoding nyingine ya Kirusi - Windows CP1251:

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

Matokeo ya kupanga, isiyo ya kawaida, yataambatana na eneo "C", na mfano mzima, ipasavyo, huendesha bila makosa. Aina fulani ya fumbo.

Sipendi fumbo katika upangaji kwa sababu kawaida hufunika makosa. Itabidi tuangalie kwa umakini jinsi inavyofanya kazi. aina na inaathiri nini? LC_COLLATE .

Mwishoni nitajaribu kujibu maswali:

  • kwa nini majina ya ukoo ya kike yalipangwa vibaya?
  • kwa nini LANG=ru_RU.CP1251 iligeuka kuwa sawa LANG=C
  • kwa nini aina ΠΈ kujiunga na mawazo tofauti kuhusu mpangilio wa masharti yaliyopangwa
  • kwa nini kuna makosa katika mifano yangu yote?
  • hatimaye jinsi ya kupanga kamba kwa kupenda kwako

Inapanga katika Unicode

Kituo cha kwanza kitakuwa ripoti ya kiufundi nambari 10 yenye haki Algorithm ya mgongano wa Unicode online unicode.org. Ripoti ina maelezo mengi ya kiufundi, kwa hivyo wacha nitoe muhtasari mfupi wa mawazo makuu.

Kulinganishwa β€” "kulinganisha" kamba ni msingi wa algorithm yoyote ya kupanga. Algorithms zenyewe zinaweza kutofautiana ("Bubble", "unganisha", "haraka"), lakini zote zitatumia ulinganisho wa jozi ya nyuzi ili kuamua mpangilio ambao zinaonekana.

Kupanga mifuatano katika lugha asilia ni tatizo changamano. Hata katika usimbuaji rahisi zaidi wa baiti moja, mpangilio wa herufi katika alfabeti, hata kwa njia fulani tofauti na alfabeti ya Kilatini ya Kiingereza, hautaambatana tena na mpangilio wa nambari ambazo herufi hizi zimesimbwa. Kwa hivyo katika alfabeti ya Kijerumani barua Γ– inasimama kati О ΠΈ P, na katika usimbaji CP850 yeye anapata kati ΓΏ ΠΈ Ü.

Unaweza kujaribu kutoa muhtasari kutoka kwa usimbaji maalum na kuzingatia herufi "bora" ambazo zimepangwa kwa mpangilio fulani, kama inavyofanywa katika Unicode. Usimbaji UTF8, UTF16 au baiti moja KOI8-R (ikiwa sehemu ndogo ya Unicode inahitajika) itatoa uwasilishaji tofauti wa nambari za herufi, lakini rejelea vitu sawa vya jedwali la msingi.

Inabadilika kuwa hata ikiwa tutaunda jedwali la ishara kutoka mwanzo, hatutaweza kuipa agizo la ishara kwa ulimwengu wote. Katika alfabeti tofauti za kitaifa zinazotumia herufi sawa, mpangilio wa herufi hizi unaweza kutofautiana. Kwa mfano, kwa Kifaransa Γ† itazingatiwa kama ligature na kupangwa kama kamba AE. Kwa Kinorwe Γ† itakuwa barua tofauti, ambayo iko baada ya Z. Kwa njia, pamoja na ligatures kama Γ† Kuna barua zilizoandikwa na alama kadhaa. Kwa hiyo katika alfabeti ya Kicheki kuna barua Ch, ambayo inasimama kati H ΠΈ I.

Mbali na tofauti za alfabeti, kuna mila zingine za kitaifa zinazoathiri upangaji. Hasa, swali linatokea: kwa mpangilio gani maneno yanayojumuisha herufi kubwa na ndogo yanapaswa kuonekana kwenye kamusi? Upangaji unaweza pia kuathiriwa na matumizi ya alama za uakifishaji. Kwa Kihispania, alama ya swali iliyogeuzwa hutumiwa mwanzoni mwa sentensi ya kuuliza (Je, unapenda muziki?) Katika kesi hii, ni dhahiri kwamba sentensi za kuuliza hazipaswi kuunganishwa katika nguzo tofauti nje ya alfabeti, lakini jinsi ya kupanga mistari na alama zingine za uakifishaji?

Sitakaa katika kupanga kamba katika lugha tofauti sana na za Uropa. Kumbuka kuwa katika lugha zilizo na mwelekeo wa uandishi kutoka kulia kwenda kushoto au kutoka juu hadi chini, herufi katika mistari zina uwezekano mkubwa kuhifadhiwa kwa mpangilio wa usomaji, na hata mifumo isiyo ya alfabeti ina njia zao za kupanga mistari herufi kwa herufi. . Kwa mfano, hieroglyphs zinaweza kuamuru kwa mtindo (Vifunguo vya herufi za Kichina) au kwa matamshi. Kuwa mkweli, sijui jinsi emojis zinapaswa kupangwa, lakini unaweza kuja na kitu kwao pia.

Kulingana na vipengele vilivyoorodheshwa hapo juu, mahitaji ya msingi ya kulinganisha mifuatano kulingana na majedwali ya Unicode yaliundwa:

  • kulinganisha kwa masharti haitegemei nafasi ya wahusika katika jedwali la kanuni;
  • mfuatano wa wahusika wanaounda mhusika mmoja hupunguzwa hadi umbo la kisheria (A + duara la juu ni sawa na Γ…);
  • Wakati wa kulinganisha kamba, mhusika huzingatiwa katika muktadha wa kamba na, ikiwa ni lazima, pamoja na majirani zake katika kitengo kimoja cha kulinganisha (Ch kwa Kicheki) au imegawanywa katika kadhaa (Γ† kwa Kifaransa);
  • vipengele vyote vya kitaifa (alfabeti, herufi kubwa/chini, alama za uakifishaji, mpangilio wa aina za uandishi) lazima viwekewe mipangilio hadi ukabidhi wa agizo (emoji);
  • kulinganisha ni muhimu sio tu kwa kupanga, lakini pia katika maeneo mengine mengi, kwa mfano kwa kubainisha safu za safu (kubadilisha {A... z} katika bash);
  • Ulinganisho unapaswa kufanywa haraka.

Kwa kuongezea, waandishi wa ripoti walitengeneza sifa za ulinganishi ambazo wasanidi wa kanuni za kanuni hawapaswi kutegemea:

  • algorithm ya kulinganisha haipaswi kuhitaji seti tofauti ya wahusika kwa kila lugha (lugha za Kirusi na Kiukreni hushiriki herufi nyingi za Kicyrillic);
  • kulinganisha haipaswi kutegemea utaratibu wa wahusika katika meza za Unicode;
  • uzito wa kamba haipaswi kuwa sifa ya kamba, kwa kuwa kamba sawa katika mazingira tofauti ya kitamaduni inaweza kuwa na uzito tofauti;
  • uzani wa safu inaweza kubadilika wakati wa kuunganishwa au kugawanyika (kutoka x < y haifuati hivyo xz < yz);
  • kamba tofauti zenye uzani sawa huchukuliwa kuwa sawa kutoka kwa mtazamo wa algorithm ya kupanga. Kuanzisha utaratibu wa ziada wa masharti hayo inawezekana, lakini inaweza kuharibu utendaji;
  • Wakati wa kupanga mara kwa mara, safu zenye uzani sawa zinaweza kubadilishwa. Uimara ni sifa ya algorithm maalum ya kupanga, na sio sifa ya algorithm ya kulinganisha ya kamba (tazama aya iliyotangulia);
  • Kanuni za kupanga zinaweza kubadilika kadiri mila za kitamaduni zinavyoboresha/kubadilika.

Pia imeainishwa kuwa algorithm ya kulinganisha haijui chochote kuhusu semantiki za mifuatano inayochakatwa. Kwa hivyo, kamba zinazojumuisha nambari pekee hazipaswi kulinganishwa kama nambari, na katika orodha ya majina ya Kiingereza kifungu (Beatles, The).

Ili kukidhi mahitaji yote yaliyotajwa, algorithm ya kupanga jedwali ya ngazi mbalimbali (halisi ya ngazi nne) inapendekezwa.

Hapo awali, wahusika katika kamba hupunguzwa kwa fomu ya kisheria na kuunganishwa katika vitengo vya kulinganisha. Kila kitengo cha kulinganisha kinapewa uzito kadhaa unaolingana na viwango kadhaa vya kulinganisha. Uzito wa vitengo vya kulinganisha ni vipengele vya seti zilizoagizwa (katika kesi hii, integers) ambazo zinaweza kulinganishwa kwa zaidi au chini. Maana maalum IMEPUUZWA (0x0) inamaanisha kuwa katika kiwango kinacholingana cha ulinganisho kitengo hiki hakihusiki katika ulinganisho. Ulinganisho wa masharti unaweza kurudiwa mara kadhaa, kwa kutumia uzani wa viwango vinavyolingana. Katika kila ngazi, uzani wa vitengo vya kulinganisha vya nyuzi mbili hulinganishwa kwa mtiririko na kila mmoja.

Katika utekelezaji tofauti wa algorithm ya mila tofauti za kitaifa, maadili ya coefficients yanaweza kutofautiana, lakini kiwango cha Unicode ni pamoja na meza ya msingi ya uzani - "Jedwali Chaguo-msingi la Kipengele cha Ukusanyaji wa Unicode" (DUCET) Ningependa kutambua kuwa kuweka kutofautisha LC_COLLATE kwa kweli ni dalili ya uteuzi wa jedwali la uzani katika kazi ya kulinganisha ya kamba.

Vipimo vya uzani DUCET kupangwa kama ifuatavyo:

  • katika ngazi ya kwanza, barua zote zimepunguzwa kwa kesi sawa, diacritics hutupwa, alama za punctuation (sio zote) hazizingatiwi;
  • katika ngazi ya pili, diacritics tu huzingatiwa;
  • katika ngazi ya tatu, kesi pekee inazingatiwa;
  • katika ngazi ya nne, alama za uakifishaji pekee huzingatiwa.

Ulinganisho unafanyika katika kupita kadhaa: kwanza, coefficients ya ngazi ya kwanza inalinganishwa; ikiwa uzani unaambatana, basi kulinganisha mara kwa mara na uzani wa kiwango cha pili hufanywa; basi labda ya tatu na ya nne.

Ulinganisho huisha wakati safu mlalo zina vitengo vinavyolingana vya ulinganisho na uzani tofauti. Safu ambazo zina uzani sawa katika viwango vyote vinne huchukuliwa kuwa sawa kwa kila mmoja.

Kanuni hii (iliyo na rundo la maelezo ya ziada ya kiufundi) ilitoa jina la kuripoti Nambari 10 - "Algorithm ya Ukusanyaji wa Unicode" (ACU).

Hapa ndipo tabia ya kupanga kutoka kwa mfano wetu inakuwa wazi kidogo. Itakuwa nzuri kulinganisha na kiwango cha Unicode.

Ili kujaribu utekelezaji ACU kuna maalum mtihani, kutumia uzani faili, kutekeleza DUCET. Unaweza kupata kila aina ya vitu vya kuchekesha kwenye faili ya mizani. Kwa mfano, kuna mpangilio wa mahjong na domino za Uropa, na vile vile mpangilio wa suti kwenye safu ya kadi (ishara). 1F000 na zaidi). Suti za kadi zimewekwa kulingana na sheria za daraja - PCBT, na kadi katika suti ziko katika mlolongo T, 2,3, XNUMX... K.

Kuangalia mwenyewe kuwa safu zimepangwa kwa usahihi kulingana na DUCET itakuwa ya kuchosha sana, lakini, kwa bahati nzuri kwetu, kuna utekelezaji wa mfano wa maktaba ya kufanya kazi na Unicode - "Vipengele vya Kimataifa vya Unicode"(ICU).

Kwenye wavuti ya maktaba hii, iliyoandaliwa katika IBM, kuna kurasa za onyesho, pamoja na ukurasa wa algorithm ya kulinganisha kamba. Tunaingiza mistari yetu ya majaribio na mipangilio chaguo-msingi na, tazama, tunapata upangaji kamili wa Kirusi.

Абаканов ΠœΠΈΡ…Π°ΠΈΠ»;маляр
Ёлкина Π­Π»Π»Π°;ΠΊΡ€Π°Π½ΠΎΠ²Ρ‰ΠΈΡ†Π°
Иванов АндрСй;ΡΠ»Π΅ΡΠ°Ρ€ΡŒ
Иванова Алла;Π°Π΄Π²ΠΎΠΊΠ°Ρ‚

Kwa njia, tovuti ICU Unaweza kupata ufafanuzi wa algorithm ya kulinganisha wakati wa kuchakata alama za uakifishaji. Katika mifano Maswali Yanayoulizwa Mara kwa Mara kiapostrofi na viambatisho havizingatiwi.

Unicode ilitusaidia, lakini tafuta sababu za tabia ya kushangaza aina Π² Linux itabidi aende mahali pengine.

Inapanga katika glibc

Mwonekano wa haraka wa misimbo ya chanzo cha matumizi aina ya Matumizi ya Msingi ya GNU ilionyesha kuwa katika matumizi yenyewe, ujanibishaji huja hadi kuchapisha thamani ya sasa ya kutofautisha LC_COLLATE wakati wa kuendesha katika hali ya kurekebisha:

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

Ulinganisho wa kamba unafanywa kwa kutumia kazi ya kawaida stroll, ambayo inamaanisha kuwa kila kitu kinachovutia kiko kwenye maktaba glibc.

Cha wiki ya mradi huo glibc kujitolea kwa kulinganisha kamba aya moja. Kutoka kwa aya hii inaweza kueleweka kuwa katika glibc kupanga kunategemea algoriti ambayo tayari tunaijua ACU (Algorithm ya mgongano wa Unicode) na/au kwa kiwango karibu nayo ISO 14651 (Kuagiza kamba ya kimataifa na kulinganisha) Kuhusu kiwango cha hivi karibuni, ni lazima ieleweke kwamba kwenye tovuti viwango.iso.org ISO 14651 kutangazwa rasmi kwa umma, lakini kiungo sambamba kinaongoza kwa ukurasa ambao haupo. Google inarudi kurasa kadhaa zilizo na viungo vya tovuti rasmi ambazo hutoa kununua nakala ya elektroniki ya kiwango cha euro mia moja, lakini kwenye ukurasa wa tatu au wa nne wa matokeo ya utafutaji pia kuna viungo vya moja kwa moja PDF. Kwa ujumla, kiwango ni kivitendo hakuna tofauti na ACU, lakini inachosha zaidi kusoma kwa sababu haina mifano wazi ya vipengele vya kitaifa vya kupanga kamba.

Habari ya kuvutia zaidi juu ya wiki kulikuwa na kiungo cha mfuatiliaji wa mdudu na mjadala wa utekelezaji wa ulinganifu wa kamba katika glibc. Kutoka kwa majadiliano inaweza kujifunza kwamba glibc hutumika kulinganisha mistari ISOmeza ya kibinafsi Jedwali la Kiolezo cha Kawaida (CTT), anwani ambayo inaweza kupatikana katika programu A kiwango ISO 14651. Kati ya 2000 na 2015 jedwali hili katika glibc haikuwa na mtunzaji na ilikuwa tofauti kabisa (angalau nje) kutoka kwa toleo la sasa la kiwango. Kuanzia 2015 hadi 2018, marekebisho ya toleo jipya la jedwali yalifanyika, na sasa una nafasi ya kukutana katika maisha halisi toleo jipya la meza (CentOS 8), na mzee (CentOS 7).

Sasa kwa kuwa tuna habari zote kuhusu algorithm na meza za msaidizi, tunaweza kurudi kwenye tatizo la awali na kuelewa jinsi ya kupanga kwa usahihi masharti katika lugha ya Kirusi.

ISO 14651 / 14652

Msimbo wa chanzo wa jedwali tunalovutiwa nalo CTT kwenye usambazaji mwingi Linux iko kwenye katalogi /usr/share/i18n/locales/. Jedwali lenyewe liko kwenye faili iso14651_t1_kawaida. Kisha hii ni maagizo ya faili nakala iso14651_t1_kawaida imejumuishwa kwenye faili iso14651_t1, ambayo, kwa upande wake, imejumuishwa katika faili za kitaifa, ikiwa ni pamoja na en_US ΠΈ ru_RU. Kwenye usambazaji mwingi Linux faili zote za chanzo zinajumuishwa katika usakinishaji wa msingi, lakini ikiwa hazipo, itabidi usakinishe kifurushi cha ziada kutoka kwa usambazaji.

Muundo wa faili iso14651_t1 inaweza kuonekana kuwa ya kitenzi sana, na sheria zisizo wazi za kuunda majina, lakini ukiiangalia, kila kitu ni rahisi sana. Muundo umeelezewa katika kiwango ISO 14652, nakala ambayo inaweza kupakuliwa kutoka kwa tovuti open-std.org. Maelezo mengine ya umbizo la faili yanaweza kusomwa ndani vipimo POSIX kutoka OpenGroup. Kama mbadala ya kusoma kiwango, unaweza kusoma msimbo wa chanzo cha chaguo la kukokotoa kusanya_soma Π² glibc/locale/programs/ld-collate.c.

Muundo wa faili unaonekana kama hii:

Kwa chaguomsingi, herufi hutumika kama herufi ya kutoroka, na mwisho wa mstari baada ya herufi # ni maoni. Alama zote mbili zinaweza kufafanuliwa upya, ambayo ndiyo inafanywa katika toleo jipya la jedwali:

escape_char /
comment_char %

Faili itakuwa na ishara katika umbizo au (Wapi x - tarakimu ya hexadecimal). Huu ni uwakilishi wa hexadecimal wa alama za msimbo wa Unicode katika usimbaji UCS-4 (UTF-32) Vipengele vingine vyote kwenye mabano ya pembe (pamoja na , <2> na mengineyo) huchukuliwa kuwa viunga rahisi vya kamba ambavyo vina maana kidogo nje ya muktadha.

Kamba LC_COLLATE inatuambia kwamba inayofuata huanza data inayoelezea ulinganisho wa kamba.

Kwanza, majina yamebainishwa kwa uzani kwenye jedwali la kulinganisha na majina ya mchanganyiko wa alama. Kwa ujumla, aina hizi mbili za majina ni za vyombo viwili tofauti, lakini katika faili halisi zimechanganywa. Majina ya uzani yanatajwa na neno kuu ishara ya kuunganisha (tabia ya kulinganisha) kwa sababu wakati wa kulinganisha, herufi za Unicode ambazo zina uzani sawa zitazingatiwa herufi sawa.

Urefu wa jumla wa sehemu katika marekebisho ya sasa ya faili ni kama mistari 900. Nilitoa mifano kutoka sehemu kadhaa ili kuonyesha usuluhishi wa majina na aina kadhaa za sintaksia.

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>"

  • ishara ya kuunganisha magogo kamba OSMANYA katika jedwali la majina ya mizani
  • ishara ya kuunganisha .. husajili mfuatano wa majina unaojumuisha kiambishi awali S na kiambishi tamati cha heksadesimali kutoka 1D000 kwa 1D35F.
  • FFF Π² ishara ya kuunganisha inaonekana kama nambari kubwa isiyo na saini katika hexadecimal, lakini ni jina tu ambalo linaweza kuonekana kama
  • jina inamaanisha sehemu ya nambari katika usimbuaji UCS-4
  • kipengele cha kuunganisha kutoka" " husajili jina jipya kwa jozi ya nukta za Unicode.

Mara tu majina ya uzani yanafafanuliwa, uzani halisi hubainishwa. Kwa kuwa uhusiano mkubwa zaidi kuliko-chini pekee ndio muhimu kwa kulinganisha, uzani huamuliwa na mlolongo rahisi wa majina ya kuorodhesha. Vipimo vya "nyepesi" vimeorodheshwa kwanza, kisha "nzito" zaidi. Acha nikukumbushe kuwa kila herufi ya Unicode imepewa uzani nne tofauti. Hapa wameunganishwa katika mlolongo mmoja ulioamriwa. Kinadharia, jina lolote la ishara linaweza kutumika katika viwango vyovyote kati ya vinne, lakini maoni yanaonyesha kuwa wasanidi hutenganisha majina katika viwango kiakili.

% 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

Hatimaye, meza halisi ya uzito.

Sehemu ya uzani imefungwa katika mistari ya maneno muhimu order_start ΠΈ agizo_mwisho. Chaguzi za ziada order_start kuamua ni mwelekeo gani safu huchanganuliwa katika kila kiwango cha kulinganisha. Mpangilio chaguo-msingi ni mbele. Mwili wa sehemu hiyo una mistari iliyo na msimbo wa ishara na uzani wake nne. Msimbo wa herufi unaweza kuwakilishwa na mhusika yenyewe, nukta ya msimbo, au jina la ishara lililofafanuliwa hapo awali. Uzito pia unaweza kutolewa kwa majina ya ishara, alama za msimbo, au alama zenyewe. Ikiwa pointi za msimbo au wahusika hutumiwa, uzito wao ni sawa na thamani ya nambari ya hatua ya msimbo (nafasi katika jedwali la Unicode). Vibambo ambavyo havijabainishwa waziwazi (kama ninavyoelewa) huchukuliwa kuwa kwa ajili ya jedwali lenye uzito msingi unaolingana na nafasi katika jedwali la Unicode. Thamani maalum ya uzito PUZA inamaanisha kuwa ishara inapuuzwa katika kiwango kinachofaa cha kulinganisha.

Ili kuonyesha muundo wa mizani, nilichagua vipande vitatu dhahiri:

  • wahusika ambao wamepuuzwa kabisa
  • alama sawa na nambari tatu katika viwango viwili vya kwanza
  • mwanzo wa alfabeti ya Cyrillic, ambayo haina diacritics, na kwa hiyo hupangwa hasa na ngazi ya kwanza na ya tatu.

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

Sasa unaweza kurudi kupanga mifano tangu mwanzo wa kifungu. Kuvizia iko katika sehemu hii ya jedwali la uzani:

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

Inaweza kuonekana kuwa katika jedwali hili alama za uakifishaji kutoka kwenye jedwali ASCII (pamoja na nafasi) karibu kila wakati hupuuzwa wakati wa kulinganisha kamba. Vighairi pekee ni mistari inayolingana katika kila kitu isipokuwa alama za uakifishaji zinazopatikana katika nafasi zinazolingana. Mistari kutoka kwa mfano wangu (baada ya kupanga) kwa algorithm ya kulinganisha inaonekana kama hii:

ΠΠ±Π°ΠΊΠ°Π½ΠΎΠ²ΠœΠΈΡ…Π°ΠΈΠ»ΠΌΠ°Π»ΡΡ€
ЁлкинаЭллакрановщица
Π˜Π²Π°Π½ΠΎΠ²Π°ΠΠ»Π»Π°ΠΌΠ°Π»ΡΡ€
Π˜Π²Π°Π½ΠΎΠ²ΠΠ½Π΄Ρ€Π΅ΠΉΡΠ»Π΅ΡΠ°Ρ€ΡŒ

Kwa kuzingatia kwamba katika jedwali la mizani, herufi kubwa katika Kirusi huja baada ya herufi ndogo (katika ngazi ya tatu nzito kuliko ), upangaji unaonekana kuwa sawa kabisa.

Wakati wa kuweka variable LC_COLLATE=C meza maalum ni kubeba ambayo inabainisha ulinganisho wa byte-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'
};

Kwa kuwa katika Unicode nukta ya msimbo Ё inakuja kabla ya A, masharti yanapangwa ipasavyo.

Maandishi na meza za binary

Ni wazi, kulinganisha kwa kamba ni operesheni ya kawaida sana, na uchanganuzi wa jedwali CTT utaratibu wa gharama kubwa kabisa. Ili kuongeza ufikiaji wa jedwali, imejumuishwa katika fomu ya binary na amri localdef.

Timu localdef inakubali kama vigezo faili iliyo na jedwali la sifa za kitaifa (chaguo -i), ambapo herufi zote zinawakilishwa na dots za Unicode, na faili ya mawasiliano kati ya nukta za Unicode na herufi za usimbaji maalum (chaguo -f) Kama matokeo ya kazi, faili za binary huundwa kwa eneo na jina lililowekwa kwenye parameta ya mwisho.

glibc inasaidia fomati mbili za faili za binary: "jadi" na "kisasa".

Umbizo la jadi linamaanisha kuwa jina la eneo ni jina la saraka ndogo ndani /usr/lib/locale/. Orodha hii ndogo huhifadhi faili za binary LC_COLLATE, LC_CTYPE, LC_TIME Nakadhalika. Faili LC_IDENTIFICATION ina jina rasmi la eneo (ambalo linaweza kuwa tofauti na jina la saraka) na maoni.

Umbizo la kisasa linajumuisha kuhifadhi lugha zote kwenye kumbukumbu moja /usr/lib/locale/locale-archive, ambayo imechorwa kwa kumbukumbu pepe ya michakato yote inayotumia glibc. Jina la eneo katika umbizo la kisasa linaweza kutangazwa kuwa mtakatifu - nambari na herufi zilizopunguzwa hadi herufi ndogo ndizo zinazosalia katika majina ya usimbaji. Hivyo ru_RU.KOI8-R, itahifadhiwa kama ru_RU.koi8r.

Faili za ingizo hutafutwa katika saraka ya sasa, na pia katika saraka /usr/share/i18n/locales/ ΠΈ /usr/share/i18n/charmaps/ kwa faili CTT na faili za usimbaji, kwa mtiririko huo.

Kwa mfano, amri

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

itakusanya faili /usr/share/i18n/locales/ru_RU kwa kutumia faili ya encoding /usr/share/i18n/charmaps/MAC-CYRILLIC.gz na uhifadhi matokeo ndani /usr/lib/locale/locale-archive chini ya jina ru_RU.maccyrillic

Ikiwa utaweka kutofautisha LANG = en_US.UTF-8 hiyo glibc itatafuta jozi za eneo katika mlolongo ufuatao wa faili na saraka:

/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/

Ikiwa eneo hutokea katika muundo wa jadi na wa kisasa, basi kipaumbele kinatolewa kwa kisasa.

Unaweza kutazama orodha ya maeneo yaliyokusanywa na amri locale -a.

Kuandaa meza yako ya kulinganisha

Sasa, ukiwa na maarifa, unaweza kuunda jedwali lako bora la ulinganifu wa kamba. Jedwali hili linapaswa kulinganisha kwa usahihi barua za Kirusi, ikiwa ni pamoja na barua Ё, na wakati huo huo kuzingatia alama za alama kwa mujibu wa meza. ASCII.

Mchakato wa kuandaa jedwali lako la kupanga lina hatua mbili: kuhariri jedwali la uzani na kuikusanya katika fomu ya binary na amri. localdef.

Ili jedwali la kulinganisha lirekebishwe kwa gharama ndogo za uhariri, katika umbizo ISO 14652 Sehemu za kurekebisha uzito wa meza iliyopo hutolewa. Sehemu huanza na neno kuu panga upya-baada na kuonyesha nafasi baada ya ambayo uingizwaji unafanywa. Sehemu inaisha na mstari panga upya-mwisho. Ikiwa ni muhimu kurekebisha sehemu kadhaa za meza, basi sehemu imeundwa kwa kila sehemu hiyo.

Nilinakili matoleo mapya ya faili iso14651_t1_kawaida ΠΈ ru_RU kutoka kwa hazina glibc kwa saraka yangu ya nyumbani ~/.local/share/i18n/locales/ na kuhariri sehemu kidogo LC_COLLATE Π² ru_RU. Matoleo mapya ya faili yanaoana kikamilifu na toleo langu glibc. Ikiwa unataka kutumia matoleo ya zamani ya faili, itabidi ubadilishe majina ya ishara na mahali ambapo uingizwaji unaanzia kwenye jedwali.

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

Kwa kweli, itakuwa muhimu kubadilisha shamba ndani LC_IDENTIFICATION ili waelekeze eneo ru_MY, lakini kwa mfano wangu hii haikuhitajika, kwani nilitenga kumbukumbu kutoka kwa utaftaji wa maeneo hifadhi ya eneo.

Hiyo localdef ilifanya kazi na faili kwenye folda yangu kupitia kutofautisha I18NPATH Unaweza kuongeza saraka ya ziada kutafuta faili za ingizo, na saraka ya kuhifadhi faili za binary inaweza kubainishwa kama njia iliyo na mikwaju:

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

POSIX inadhani kuwa katika LUGHA unaweza kuandika njia kabisa za saraka zilizo na faili za eneo, ukianza na kufyeka mbele, lakini glibc Π² Linux njia zote zinahesabiwa kutoka kwa saraka ya msingi, ambayo inaweza kubatilishwa kupitia kutofautisha LOCPATH. Baada ya ufungaji LOCPATH=~/.local/lib/locale/ faili zote zinazohusiana na ujanibishaji zitatafutwa kwenye folda yangu pekee. Hifadhi ya lugha zilizo na seti tofauti LOCPATH kupuuzwa.

Hapa kuna mtihani wa kuamua:

$> LANG=ru_MY.UTF-8 LOCPATH=~/.local/lib/locale/ sort buhg.txt
Абаканов ΠœΠΈΡ…Π°ΠΈΠ»;маляр
Ёлкина Π­Π»Π»Π°;ΠΊΡ€Π°Π½ΠΎΠ²Ρ‰ΠΈΡ†Π°
Иванов АндрСй;ΡΠ»Π΅ΡΠ°Ρ€ΡŒ
Иванова Алла;Π°Π΄Π²ΠΎΠΊΠ°Ρ‚

Hooray! Tulifanya!

Baadhi ya makosa ya

Tayari nimejibu maswali kuhusu kupanga kamba yaliyotolewa mwanzoni, lakini bado kuna maswali kadhaa kuhusu makosa - yanayoonekana na yasiyoonekana.

Hebu turudi kwenye tatizo la awali.

Na programu aina na programu kujiunga na tumia kazi sawa za kulinganisha kamba kutoka glibc. Ilifanyikaje hivyo kujiunga na alitoa hitilafu ya kupanga kwenye safu zilizopangwa kwa amri aina katika eneo sw_US.UTF-8? Jibu ni rahisi: aina inalinganisha kamba nzima, na kujiunga na inalinganisha ufunguo pekee, ambao kwa chaguo-msingi ni mwanzo wa kamba hadi herufi ya kwanza ya nafasi nyeupe. Katika mfano wangu, hii ilisababisha ujumbe wa makosa kwa sababu upangaji wa maneno ya kwanza kwenye mistari haukulingana na upangaji wa mistari kamili.

Eneo "C" inahakikisha kwamba katika mifuatano iliyopangwa vifungu vidogo vya mwanzo hadi nafasi ya kwanza pia vitapangwa, lakini hii hufunika tu hitilafu. Inawezekana kuchagua data (watu walio na majina sawa, lakini majina tofauti ya kwanza) ambayo, bila ujumbe wa makosa, inaweza kutoa matokeo yasiyo sahihi ya kuunganisha faili. Ikiwa tunataka kujiunga na mistari ya faili iliyounganishwa kwa jina kamili, basi njia sahihi itakuwa kutaja kitenganishi cha uga kwa uwazi na kupanga kwa uga wa ufunguo, na si kwa mstari mzima. Katika kesi hii, kuunganisha kutaendelea kwa usahihi na hakutakuwa na makosa katika eneo lolote:

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

Imetekelezwa kwa ufanisi mfano katika usimbaji CP1251 ina hitilafu nyingine. Ukweli ni kwamba katika usambazaji wote unaojulikana kwangu Linux vifurushi vinakosa lugha iliyokusanywa ru_RU.CP1251. Ikiwa eneo lililokusanywa halipatikani, basi aina kimya hutumia kulinganisha kwa byte-byte, ambayo ndio tuliona.

Kwa njia, kuna glitch nyingine ndogo inayohusiana na kutopatikana kwa maeneo yaliyokusanywa. Timu LOCPATH=/tmp eneo -a itatoa orodha ya maeneo yote ndani hifadhi ya eneo, lakini na seti ya kutofautisha LOCPATH kwa programu zote (pamoja na zaidi ndani) lugha hizi hazitapatikana.

$> 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

Hitimisho

Ikiwa wewe ni programu ambaye amezoea kufikiria kuwa kamba ni seti ya ka, basi chaguo lako LC_COLLATE=C.

Iwapo wewe ni mtaalamu wa lugha au mkusanyaji wa kamusi, basi ni bora uunge katika lugha yako.

Ikiwa wewe ni mtumiaji rahisi, basi unahitaji tu kuzoea ukweli kwamba amri ls -a hutoa faili zinazoanza na nukta iliyochanganywa na faili zinazoanza na herufi, na Kamanda wa usiku wa manane, ambayo hutumia vitendaji vyake vya ndani kupanga majina, huweka faili kuanzia na nukta mwanzoni mwa orodha.

marejeo

Ripoti nambari 10 ya mgongano wa algoriti

Vipimo vya wahusika katika unicode.org

ICU - utekelezaji wa maktaba ya kufanya kazi na Unicode kutoka IBM.

Mtihani wa kupanga kwa kutumia ICU

Uzito wa tabia ndani ISO 14651

Maelezo ya umbizo la faili na mizani ISO 14652

Majadiliano ya kulinganisha kamba katika glibc

Chanzo: mapenzi.com

Kuongeza maoni