perkenalan
Éta sadayana dimimitian ku naskah pondok anu sakuduna ngagabungkeun inpormasi alamat email karyawan dicandak tina daptar pamaké milis, jeung posisi pagawe dicandak ti database departemen HR. Kadua daptar diékspor ka file téks Unicode UTF-8 tur disimpen ku tungtung garis Unix.
Eusi mail.txt
Иванов Андрей;ia@example.comEusi buhg.txt
Иванова Алла;маляр
Ёлкина Элла;крановщица
Иванов Андрей;слесарь
Абаканов Михаил;малярPikeun ngagabung, file diurutkeun ku paréntah Unix dipilihan sarta dikintunkeun kana input program Unix gabung, nu teu disangka-sangka gagal ku kasalahan:
$> sort buhg.txt > buhg.srt
$> sort mail.txt > mail.srt
$> join buhg.srt mail.srt > result
join: buhg.srt:4: is not sorted: Иванов Андрей;слесарьNingali hasil asihan ku panon anjeun nunjukkeun yén, sacara umum, asihan leres, tapi dina kasus kabeneran ngaran kulawarga jalu sareng awéwé, anu awéwé sateuacanna lalaki:
$> sort buhg.txt
Абаканов Михаил;маляр
Ёлкина Элла;крановщица
Иванова Алла;маляр
Иванов Андрей;слесарьSigana mah glitch asihan dina Unicode atanapi sapertos manifestasi feminisme dina algoritma asihan. Anu kahiji, tangtosna, langkung masuk akal.
Hayu urang ditunda pikeun ayeuna gabung jeung fokus kana dipilihan. Hayu urang cobaan pikeun ngajawab masalah ngagunakeun poking ilmiah. Kahiji, hayu urang ngaganti lokal tina di AS dina ru_RU. Pikeun nyortir, éta bakal cekap pikeun nyetél variabel lingkungan LC_COLLATE, tapi urang moal miceunan waktos pikeun hal-hal anu teu penting:
$> LANG=ru_RU.UTF-8 sort buhg.txt
Абаканов Михаил;маляр
Ёлкина Элла;крановщица
Иванова Алла;маляр
Иванов Андрей;слесарьEuweuh nu robah.
Hayu urang cobian recode file kana encoding bait tunggal:
$> iconv -f UTF-8 -t KOI8-R buhg.txt
| LANG=ru_RU.KOI8-R sort
| iconv -f KOI8-R -t UTF8Deui nanaon geus robah.
Henteu aya anu anjeun tiasa laksanakeun, anjeun kedah milarian solusi dina Internét. Aya nanaon langsung ngeunaan ngaran kulawarga Rusia, tapi aya patarosan ngeunaan oddities asihan lianna. Contona, ieu masalah: . Pondokna, senar "ab", "aa", "ac" diurutkeun jadi "aa", "ab", "ac".
Jawabanna standar dimana waé: nganggo lokal programmer "C" tur anjeun bakal senang. Hayu urang coba:
$> LANG=C sort buhg.txt
Ёлкина Элла;крановщица
Абаканов Михаил;маляр
Иванов Андрей;слесарь
Иванова Алла;адвокатAya nu robah. Ivanovs dijejeran dina urutan bener, sanajan Yolkina slipped wae. Hayu urang balik deui ka masalah aslina:
$> LANG=C sort buhg.txt > buhg.srt
$> LANG=C sort mail.txt > mail.srt
$> LANG=C join buhg.srt mail.srt > resultGawéna tanpa kasalahan, sakumaha jangji Internét. Sarta ieu sanajan Yolkina dina baris kahiji.
Masalahna sigana bakal direngsekeun, tapi bisi waé, cobian panyandian Rusia anu sanés - Windows CP1251:
$> iconv -f UTF-8 -t CP1251 buhg.txt
| LANG=ru_RU.CP1251 sort
| iconv -f CP1251 -t UTF8 Hasil asihan, cukup aneh, bakal coincide jeung lokal "C", sarta sakabeh conto, sasuai, ngajalankeun tanpa kasalahan. Sababaraha jenis mistisisme.
Abdi henteu resep mistik dina program sabab biasana masker kasalahan. Urang kedah serius ningali kumaha jalanna. dipilihan sareng naon pangaruhna? LC_COLLATE .
Dina tungtungna kuring bakal nyoba ngajawab patarosan:
- naha ngaran kulawarga awéwé salah diurutkeun?
- naha LANG=ru_RU.CP1251 tétéla sarua LANG=C
- naha ngalakukeun dipilihan и gabung gagasan béda ngeunaan urutan string diurutkeun
- naha aya kasalahan dina sakabéh conto kuring?
- tungtungna kumaha nyortir string ka liking Anjeun
Asihan dina Unicode
Eureun heula bakal laporan teknis No.. 10 judulna online . Laporan éta ngandung seueur rinci téknis, janten kuring masihan kasimpulan ideu utama.
gabungan - "ngabandingkeun" string mangrupakeun dasar tina sagala algoritma asihan. Algoritma sorangan bisa béda ("gelembung", "ngagabung", "gancang"), tapi aranjeunna sadayana bakal ngagunakeun ngabandingkeun tina sapasang string pikeun nangtukeun urutan nu maranéhna muncul.
Asihan string dina basa alam mangrupakeun masalah anu cukup kompleks. Malah dina encodings single-bait pangbasajanna, urutan hurup dina alfabét, sanajan dina sababaraha cara béda ti alfabét Latin Inggris, moal deui coincide jeung urutan nilai numerik nu hurup ieu disandi. Jadi dina alfabét Jerman hurup Ö nangtung diantara О и P, sarta dina encoding CP850 manehna meunang antara ÿ и Ü.
Anjeun tiasa nyobian abstrak tina encoding khusus sareng mertimbangkeun hurup "ideal" anu disusun dina sababaraha urutan, sapertos anu dilakukeun dina Unicode. Encodings UTF8, UTF16 atawa hiji-bait KOI8-R (lamun sawaréh kawates Unicode diperlukeun) bakal mere representasi numerik béda tina hurup, tapi tingal elemen sarua tabel dasar.
Tétéla yén sanajan urang ngawangun tabel simbol ti scratch, urang moal bisa napelkeun urutan simbol universal pikeun eta. Dina alfabét nasional anu béda anu ngagunakeun hurup anu sami, urutan hurup ieu tiasa bénten. Contona, dina basa Perancis Æ bakal dianggap ligature sarta diurutkeun sakumaha string a AE. Dina basa Norwégia Æ bakal hurup misah, nu lokasina sanggeus Z. Ku jalan kitu, salian ligatures kawas Æ Aya hurup anu ditulis ku sababaraha simbol. Jadi dina aksara Czech aya hurup Ch, nu nangtung diantara H и I.
Salian bédana dina aksara, aya tradisi nasional séjén anu mangaruhan asihan. Khususna, patarosan timbul: dina urutan naon kecap anu diwangun ku hurup ageung sareng hurup leutik kedah muncul dina kamus? Asihan ogé bisa kapangaruhan ku pamakéan tanda baca. Dina basa Spanyol, tanda tanya inverted dipaké dina awal kalimah interogatif (Naha anjeun resep musik?). Dina hal ieu, écés yén kalimat interogatif henteu kedah dikelompokkeun kana klaster anu misah di luar alfabét, tapi kumaha carana nyortir garis sareng tanda baca anu sanés?
Kuring moal cicing dina nyortir string dina basa béda pisan ti Éropa. Catet yén dina basa anu arah tulisan katuhu-ka-kénca atawa luhur-ka-handap, karakter dina garis paling dipikaresep disimpen dina urutan bacaan, komo sistem tulisan non-alfabét boga cara sorangan susunan garis karakter ku karakter. . Contona, hiéroglif bisa diurutkeun dumasar gaya () atawa ku lafal. Jujur, kuring henteu terang kumaha carana ngatur emojis, tapi anjeun ogé tiasa ngadamel hal pikeun aranjeunna.
Dumasar kana fitur anu didaptarkeun di luhur, syarat dasar pikeun ngabandingkeun string dumasar kana tabel Unicode dirumuskeun:
- ngabandingkeun string henteu gumantung kana posisi karakter dina tabel kode;
- runtuyan karakter ngabentuk hiji karakter diréduksi jadi wangun kanonik (A + bunderan luhur sarua jeung Å);
- Nalika ngabandingkeun senar, karakter dianggap dina konteks senar sareng, upami diperyogikeun, digabungkeun sareng tatanggana kana hiji unit ngabandingkeun (Ch dina Czech) atanapi dibagi kana sababaraha (Æ dina basa Perancis);
- sagala fitur nasional (alfabét, uppercase / leutik, tanda baca, urutan jenis tulisan) kudu ngonpigurasi nepi ka ngerjakeun manual urutan (emoji);
- ngabandingkeun penting henteu ngan pikeun asihan, tapi ogé di loba tempat séjén, contona pikeun nangtukeun rentang baris (ngaganti {A... z} dina bash);
- ngabandingkeun kudu dipigawé cukup gancang.
Salaku tambahan, pangarang laporan ngarumuskeun sipat perbandingan anu henteu kedah diandelkeun ku pamekar algoritma:
- Algoritma babandingan henteu kedah meryogikeun set karakter anu misah pikeun tiap basa (basa Rusia sareng Ukrania ngabagi paling karakter Sirilik);
- ngabandingkeun teu kedah ngandelkeun urutan karakter dina tabel Unicode;
- beurat string teu kudu atribut string, saprak string sarua dina konteks budaya béda bisa boga beurat béda;
- beurat baris bisa robah nalika ngahiji atawa pamisah (tina x < y éta henteu nuturkeun éta xz < yz);
- string béda ngabogaan beurat sarua dianggap sarua tina sudut pandang tina algoritma asihan. Ngawanohkeun susunan tambahan tina string misalna mungkin, tapi bisa ngaruksak kinerja;
- Salila asihan terus-terusan, barisan anu beuratna sami tiasa diganti. Kakuatan mangrupikeun sipat algoritma asihan khusus, sareng sanés milik algoritma perbandingan string (tingali paragraf sateuacana);
- Aturan asihan tiasa robih kana waktosna nalika tradisi budaya nyaring / robih.
Hal ieu ogé diatur yén algoritma babandingan weruh nanaon ngeunaan semantik tina string keur diolah. Ku kituna, string anu ngan diwangun ku digit teu kudu dibandingkeun salaku angka, sarta dina daptar ngaran Inggris artikel (Beatles, The).
Dina raraga nyugemakeun sagala sarat dieusian, a multi-tingkat (sabenerna opat-tingkat) algoritma asihan tabel diusulkeun.
Saméméhna, karakter dina senar diréduksi jadi formulir canonical sarta dikelompokkeun kana unit ngabandingkeun. Unggal unit ngabandingkeun ditugaskeun sababaraha beurat pakait jeung sababaraha tingkatan ngabandingkeun. Beurat unit ngabandingkeun nyaéta unsur susunan susunan (dina hal ieu, integer) nu bisa dibandingkeun pikeun leuwih atawa kurang. Harti husus DIPOÉH (0x0) hartina dina tingkat babandingan pakait Unit ieu teu aub dina ngabandingkeun. Perbandingan senar tiasa diulang sababaraha kali, nganggo beurat tingkat anu saluyu. Dina unggal tingkat, beurat unit pangbanding dua jajar sacara berurutan dibandingkeun.
Dina palaksanaan algoritma anu béda pikeun tradisi nasional anu béda, nilai-nilai koefisien tiasa bénten, tapi standar Unicode kalebet tabel dasar beurat - "Tabel Unsur Koléksi Unicode Default" (DUCET). Abdi hoyong dicatet yén netepkeun variabel LC_COLLATE sabenerna mangrupa indikasi seleksi tabel beurat dina fungsi ngabandingkeun string.
Koéfisién beurat DUCET disusun saperti kieu:
- dina tingkat kahiji, sadaya hurup diréduksi jadi hal anu sarua, diakritik dipiceun, tanda baca (teu kabeh) teu dipalire;
- dina tingkat kadua, ukur diakritik anu dipertimbangkeun;
- dina tingkat katilu, ngan ukur kasus;
- dina tingkat kaopat, ngan ukur tanda baca anu diperhatikeun.
Perbandingan lumangsung dina sababaraha pas: kahiji, koefisien tingkat kahiji dibandingkeun; lamun beuratna coincide, lajeng ngabandingkeun ulang jeung beurat tingkat kadua dilaksanakeun; lajeng meureun katilu jeung kaopat.
Perbandingan ditungtungan nalika baris ngandung unit anu cocog pikeun ngabandingkeun sareng beurat anu béda. Baris nu boga beurat sarua dina sakabéh opat tingkatan dianggap sarua unggal lianna.
Algoritma ieu (kalawan kebat rinci teknis tambahan) masihan nami ngalaporkeun No. "Algoritma Koléksi Unicode" (ACU).
Ieu dimana paripolah asihan tina conto urang janten langkung jelas. Éta langkung saé dibandingkeun sareng standar Unicode.
Pikeun nguji palaksanaan ACU aya husus , ngagunakeun , ngalaksanakeun DUCET. Anjeun tiasa mendakan sagala jinis hal lucu dina file timbangan. Salaku conto, aya urutan mahjong sareng domino Éropa, ogé urutan jas dina dek kartu (simbol 1F000 sareng salajengna). Jas kartu disimpen dumasar kana aturan sasak - PCBT, sareng kartu dina jas aya dina sekuen T, 2,3, XNUMX... K.
Mariksa sacara manual yén baris diurutkeun leres dumasar kana DUCET bakal rada tedious, tapi, untungna pikeun urang, aya hiji palaksanaan exemplary perpustakaan pikeun gawé bareng Unicode - ""(ICU).
Dina ramatloka perpustakaan ieu, dimekarkeun dina IBM, aya kaca demo, kaasup . Kami asupkeun garis uji kami sareng setélan standar sareng, tingali, kami nampi asihan Rusia anu sampurna.
Абаканов Михаил;маляр
Ёлкина Элла;крановщица
Иванов Андрей;слесарь
Иванова Алла;адвокатKu jalan kitu, ramatloka ICU Anjeun tiasa mendakan klarifikasi algoritma ngabandingkeun nalika ngolah tanda baca. Dina conto apostrof jeung hyphen teu dipaliré.
Unicode mantuan kami, tapi néangan alesan pikeun kabiasaan aneh dipilihan в Linux kudu indit ka tempat séjén.
Asihan dina glibc
Pintonan gancang kode sumber utiliti dipilihan ti Utilitas Inti GNU nunjukkeun yén dina utilitas sorangan, lokalisasi turun pikeun nyitak nilai ayeuna variabel LC_COLLATE nalika ngajalankeun dina modeu debug:
$ sort --debug buhg.txt > buhg.srt
sort: using ‘en_US.UTF8’ sorting rulesBabandingan string dilakukeun ngagunakeun fungsi standar strcoll, nu hartina sagalana metot aya di perpustakaan glibc.
on wiki proyékna glibc dedicated ka string ngabandingkeun . Tina paragraf ieu tiasa dihartoskeun yén dina glibc asihan dumasar kana algoritma anu parantos dipikanyaho ku urang ACU (Algoritma pangumpulan Unicode) jeung/atawa dina standar deukeut eta ISO 14651 (Pesenan string internasional sareng ngabandingkeun). Ngeunaan standar panganyarna, éta kudu dicatet yén dina loka ISO 14651 sacara resmi dinyatakeun sadia pikeun umum, tapi link pakait ngarah ka kaca non-existent. Google mulangkeun sababaraha halaman anu aya tautan ka situs resmi anu nawiskeun mésér salinan éléktronik standar pikeun saratus euro, tapi dina halaman katilu atanapi kaopat hasil pamilarian aya ogé tautan langsung ka PDF. Sacara umum, standar praktis henteu béda ti ACU, Tapi leuwih boring maca sabab teu ngandung conto jelas fitur nasional asihan string.
Inpormasi anu paling pikaresepeun dina wiki aya tumbu ka kalawan sawala ngeunaan palaksanaan ngabandingkeun string di glibc. Tina éta sawala bisa ditilik yén glibc dipaké pikeun ngabandingkeun string ISOméja pribadi (CTT), alamatna tiasa dipendakan dina aplikasi A standar ISO 14651. Antara 2000 jeung 2015 tabel ieu di glibc teu boga maintainer sarta éta rada béda (sahenteuna externally) ti versi ayeuna standar. Ti 2015 nepi ka 2018, adaptasi kana versi anyar tabel lumangsung, sarta ayeuna anjeun boga kasempetan papanggih dina kahirupan nyata versi anyar tabel (CentOS 8), jeung heubeul (CentOS 7).
Ayeuna urang gaduh sadayana inpormasi ngeunaan algoritma sareng tabel bantu, urang tiasa uih deui ka masalah aslina sareng ngartos kumaha leres nyortir string dina lokal Rusia.
ISO 14651 / 14652
Kode sumber tabel kami museurkeun CTT dina kalolobaan distribusi Linux aya dina katalog /usr/share/i18n/locales/. Méja sorangan aya dina file iso14651_t1_common. Lajeng ieu file diréktif nyalin iso14651_t1_common kaasup kana file iso14651_t1, nu, kahareupna kaasup kana file nasional, kaasup di AS и ru_RU. Dina kalolobaan distribusi Linux sadaya file sumber anu kaasup kana instalasi dasar, tapi lamun maranéhna teu hadir, anjeun kudu masang pakét tambahan ti distribusi.
Struktur file iso14651_t1 mungkin sigana sangar verbose, kalawan aturan non-écés pikeun ngawangun ngaran, tapi lamun nempo eta, sagalana geus cukup basajan. Strukturna dijelaskeun dina standar ISO 14652, salinan anu tiasa diunduh tina situs wéb . Katerangan anu sanés ngeunaan format file tiasa dibaca dina POSIX от OpenGroup. Salaku alternatif pikeun maca standar, anjeun tiasa diajar kode sumber fungsina collate_read в glibc/locale/programs/ld-collate.c.
Struktur file sapertos kieu:
Sacara standar, karakter dipaké salaku karakter ngewa, sarta tungtung garis sanggeus karakter # nyaeta komentar. Kadua simbol tiasa didefinisikeun deui, nyaéta naon anu dilakukeun dina versi tabel énggal:
escape_char /
comment_char %Berkas bakal ngandung token dina formatna atawa (Dimana x - digit héksadesimal). Ieu ngagambarkeun héksadesimal titik kode Unicode dina encoding UCS-4 (UTF-32). Kabéh elemen séjén dina kurung sudut (kaasup , <2> jeung sajabana) dianggap konstanta string basajan nu boga harti saeutik luar konteks.
Jalur LC_COLLATE ngabejaan urang nu salajengna dimimitian data ngajéntrékeun ngabandingkeun string.
Kahiji, ngaran dieusian pikeun beurat dina tabel babandingan jeung ngaran pikeun kombinasi simbol. Umumna disebutkeun, dua jenis ngaran milik dua éntitas béda, tapi dina file sabenerna aranjeunna dicampurkeun. Ngaran-ngaran beurat ditangtukeun ku kecap konci collating-simbol (karakter babandingan) sabab nalika ngabandingkeun, karakter Unicode anu beuratna sarua bakal dianggap karakter sarimbag.
Panjang total bagian dina révisi file ayeuna kira-kira 900 baris. Kuring narik conto tina sababaraha tempat pikeun nunjukkeun kasawenangan nami sareng sababaraha jinis sintaksis.
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>"- collating-simbol log string a OSMANYA dina tabél ngaran timbangan
- collating-simbol .. ngadaptarkeun runtuyan ngaran nu diwangun ku prefiks S jeung heksadesimal numerik sufiks ti 1D000 ka 1D35F.
- FFFF в collating-simbol Sigana integer unsigned badag dina héksadesimal, tapi éta ngan ngaran nu bisa kasampak kawas
- nami hartina titik kode dina encoding UCS-4
- collating-unsur ti" " ngadaptar ngaran anyar pikeun sapasang titik Unicode.
Sakali nami beurat ditetepkeun, beurat saleresna ditangtukeun. Kusabab ngan ukur hubungan anu langkung ageung tibatan anu langkung ageung dibandingkeun, beuratna ditangtukeun ku sekuen saderhana daptar nami. Beurat "ringan" didaptarkeun heula, teras anu "beurat". Hayu atuh ngingetan yén unggal karakter Unicode ditugaskeun opat beurat béda. Di dieu aranjeunna digabungkeun kana hiji urutan maréntahkeun tunggal. Dina tiori, sagala ngaran simbolis bisa dipaké dina salah sahiji opat tingkat, tapi komentar nunjukkeun yén pamekar mental misahkeun ngaran kana tingkat.
% 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 ZHETungtungna, tabel beurat sabenerna.
Bagian beurat dikurilingan dina garis kecap konci pesenan_mimitian и pesenan_tungtung. Pilihan tambahan pesenan_mimitian nangtukeun arah mana baris discan dina unggal tingkat ngabandingkeun. Setélan standar nyaéta di payun. Awak bagian diwangun ku garis nu ngandung kodeu simbol jeung opat beurat na. Kodeu karakter bisa digambarkeun ku karakter sorangan, titik kode, atawa ngaran simbolis didefinisikeun saméméhna. Beurat ogé bisa dibikeun ka ngaran simbolis, titik kode, atawa simbol sorangan. Upami titik kode atanapi karakter dianggo, beuratna sami sareng nilai numerik titik kode (posisi dina tabel Unicode). Karakter anu henteu dijelaskeun sacara eksplisit (sakumaha kuring ngartos) dianggap ditugaskeun kana méja kalayan beurat primér anu cocog sareng posisi dina tabel Unicode. Nilai beurat husus TEU AYA hartina simbol anu dipaliré dina tingkat luyu ngabandingkeun.
Pikeun nunjukkeun struktur skala, kuring milih tilu fragmen anu jelas:
- karakter nu sagemblengna dipaliré
- simbol sarua jeung angka tilu dina dua tingkat kahiji
- awal alfabét Sirilik, nu teu ngandung diacritics, sarta ku kituna diurutkeun utamana ku tingkat kahiji jeung katilu.
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_endAyeuna anjeun tiasa uih deui pikeun nyortir conto ti mimiti tulisan. Serangan aya dina bagian ieu tabel timbangan:
<U0020> IGNORE;IGNORE;IGNORE;<U0020> % SPACE
<U0021> IGNORE;IGNORE;IGNORE;<U0021> % EXCLAMATION MARK
<U0022> IGNORE;IGNORE;IGNORE;<U0022> % QUOTATION MARK
...Ieu bisa ditempo yén dina tabél ieu tanda baca tina tabél ASCII (kaasup spasi) ampir sok dipaliré lamun ngabandingkeun string. Hiji-hijina pengecualian nyaéta garis anu cocog dina sagala hal iwal tanda baca anu aya dina posisi anu cocog. Garis tina conto kuring (sanggeus asihan) pikeun algoritma ngabandingkeun sapertos kieu:
АбакановМихаилмаляр
ЁлкинаЭллакрановщица
ИвановаАлламаляр
ИвановАндрейслесарьNganggap yén dina tabel skala, hurup kapital dina basa Rusia asalna saatos hurup leutik (dina tingkat katilu leuwih beurat ti ), asihan katingalina leres pisan.
Nalika netepkeun variabel LC_COLLATE=C a tabel husus dimuat nu nangtukeun bait-demi-bait ngabandingkeun
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'
};Kusabab dina Unicode titik kode Ё sateuacanna A, senarna diurutkeun sasuai.
Téks jeung tabel binér
Jelas, perbandingan string mangrupikeun operasi anu umum pisan, sareng parsing méja CTT prosedur anu cukup mahal. Pikeun ngaoptimalkeun aksés kana tabél, éta disusun kana bentuk binér kalayan paréntah localdef.
regu localdef nampi salaku parameter file sareng tabel karakteristik nasional (option -i), dimana sadaya karakter diwakilan ku titik-titik Unicode, sareng file korespondensi antara titik-titik Unicode sareng karakter tina encoding khusus (pilihan). -f). Salaku hasil tina karya, file binér dijieun pikeun lokal kalawan ngaran dieusian dina parameter panungtungan.
glibc ngarojong dua format file binér: "tradisional" jeung "modern".
Format tradisional hartosna nami lokal mangrupikeun nami subdirektori di /usr/lib/lokal/. Subdirektori ieu nyimpen file binér LC_COLLATE, LC_CTYPE, LC_TIME teras salajengna. File LC_IDENTIFICATION ngandung ngaran formal lokal (anu bisa jadi béda ti ngaran diréktori) jeung komentar.
Format modéren ngalibatkeun nyimpen sadaya daérah dina hiji arsip /usr/lib/locale/locale-archive, anu dipetakeun kana mémori virtual sadaya prosés anu nganggo glibc. Ngaran lokal dina format modéren tunduk kana sababaraha kanonisasi - ngan ukur angka sareng hurup anu diréduksi jadi hurup leutik tetep dina nami encoding. Janten ru_RU.KOI8-R, bakal disimpen salaku ru_RU.koi8r.
Payil input ditéang dina diréktori ayeuna, kitu ogé dina diréktori /usr/share/i18n/locales/ и /usr/share/i18n/charmaps/ pikeun file CTT sareng file encoding, masing-masing.
Contona, paréntah
localedef -i ru_RU -f MAC-CYRILLIC ru_RU.MAC-CYRILLICbakal nyusun file /usr/share/i18n/locales/ru_RU ngagunakeun file encoding /usr/share/i18n/charmaps/MAC-CYRILLIC.gz sareng simpen hasilna dina /usr/lib/locale/locale-archive handapeun nami ru_RU.maccyrillic
Upami anjeun nyetél variabel LANG = en_US.UTF-8 éta glibc bakal milarian binari lokal dina urutan file sareng diréktori ieu:
/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/Upami lokal aya dina format tradisional sareng modern, maka prioritas dipasihkeun ka anu modéren.
Anjeun tiasa ningali daptar lokal anu disusun ku paréntah -a Lokalisasi.
Nyiapkeun tabel ngabandingkeun Anjeun
Ayeuna, angkatan sareng pangaweruh, anjeun tiasa nyiptakeun tabel ngabandingkeun string idéal anjeun sorangan. Tabel ieu kedah leres-leres ngabandingkeun hurup Rusia, kalebet hurup Ё, sareng dina waktos anu sami tumut kana tanda baca saluyu sareng tabel. ASCII.
Prosés nyiapkeun tabel asihan anjeun sorangan diwangun ku dua tahap: ngédit tabel beurat sareng nyusun kana bentuk binér nganggo paréntah. localdef.
Supados tabel ngabandingkeun bisa disaluyukeun jeung waragad ngedit minimal, dina format nu ISO 14652 Bagian pikeun nyaluyukeun beurat tabel anu tos aya disayogikeun. Bagian dimimitian ku kecap konci susunan deui-sanggeus sareng nunjukkeun posisi saatos ngagantian dilaksanakeun. Bagian ditungtungan ku garis nyusun ulang-tungtung. Upami anjeun peryogi pikeun ngabenerkeun sababaraha bagian tina méja, maka bagian anu didamel pikeun tiap bagian sapertos kitu.
Kuring nyalin versi anyar tina file iso14651_t1_common и ru_RU ti gudang glibc ka diréktori imah kuring ~/.local/share/i18n/locales/ jeung rada diédit bagian LC_COLLATE в ru_RU. Vérsi file anyar sapinuhna cocog sareng versi kuring glibc. Upami anjeun hoyong nganggo vérsi file anu langkung lami, anjeun kedah ngarobih nami simbolis sareng tempat dimana ngagantian dimimitian dina tabél.
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_COLLATEKanyataanna, éta bakal diperlukeun pikeun ngarobah widang di LC_IDENTIFICATION ambéh maranéhanana nunjuk ka lokal ru_MY, Tapi dina conto kuring ieu teu diperlukeun, saprak kuring ngaluarkeun arsip ti pilarian pikeun Lokalisasi lokal-arsip.
yen localdef digawé kalayan file dina folder kuring ngaliwatan variabel I18NPATH Anjeun tiasa nambihan diréktori tambahan pikeun milarian file input, sareng diréktori pikeun ngahémat file binér tiasa disaluyukeun salaku jalur kalayan garis miring:
$> I18NPATH=~/.local/share/i18n localedef -i ru_RU -f UTF-8 ~/.local/lib/locale/ru_MY.UTF-8POSIX nunjukkeun yén dina BASA anjeun tiasa nyerat jalur mutlak pikeun diréktori kalayan file lokal, dimimitian ku slash maju, tapi glibc в Linux kabéh jalur diitung tina diréktori dasar, nu bisa overridden ngaliwatan variabel LOCPATH. Saatos instalasi LOCPATH=~/.local/lib/locale/ sadaya file anu aya hubunganana sareng lokalisasi bakal dipilarian ngan dina polder kuring. Arsip lokal sareng set variabel LOCPATH teu dipaliré.
Ieu tés anu penting:
$> LANG=ru_MY.UTF-8 LOCPATH=~/.local/lib/locale/ sort buhg.txt
Абаканов Михаил;маляр
Ёлкина Элла;крановщица
Иванов Андрей;слесарь
Иванова Алла;адвокатHoreeee! Urang ngalakukeun eta!
Lepatan nanganan
Kuring parantos ngawaler patarosan ngeunaan asihan string anu ditimbulkeun di awal, tapi masih aya sababaraha patarosan ngeunaan kasalahan - katingali sareng teu katingali.
Hayu urang balik deui ka masalah aslina.
Jeung program dipilihan jeung program gabung ngagunakeun fungsi ngabandingkeun string sarua ti glibc. Kumaha éta kajadian gabung masihan kasalahan asihan dina baris diurutkeun ku paréntah dipilihan di lokal en_US.UTF-8? Jawabanana basajan: dipilihan ngabandingkeun sakabéh string, jeung gabung compares ngan konci, nu sacara standar mangrupakeun awal string nepi ka karakter whitespace munggaran. Dina conto kuring, ieu nyababkeun pesen kasalahan sabab asihan kecap munggaran dina garis henteu cocog sareng asihan garis lengkep.
Lokal "C" ngajamin yén dina string diurutkeun substrings awal nepi ka spasi munggaran ogé bakal diurutkeun, tapi ieu ngan masker kasalahan. Kasebut nyaéta dimungkinkeun pikeun milih data (jalma nu ngaran kulawarga sarua, tapi ngaran hareup béda) nu, tanpa talatah kasalahan, bakal méré hasil ngagabung file lepat. Lamun urang hayang gabung ngagabung garis file ku ngaran lengkep, mangka cara nu bener bakal nangtukeun sacara eksplisit separator widang jeung diurutkeun dumasar widang konci, teu ku sakabéh garis. Dina hal ieu, ngahiji bakal diteruskeun leres sareng moal aya kasalahan dina lokal mana waé:
$> sort -t ; -k 1 buhg.txt > buhg.srt
$> sort -t ; -k 1 mail.txt > mail.srt
$> join -t ; buhg.srt mail.srt > resultHasil dieksekusi conto dina encoding CP1251 ngandung kasalahan sejen. Kanyataan yén dina sagala sebaran dipikawanoh pikeun kuring Linux bungkusan leungit lokal disusun ru_RU.CP1251. Upami lokal anu disusun henteu kapendak, maka dipilihan cicingeun ngagunakeun bait-demi-bait ngabandingkeun, nu urang observasi.
Ku jalan kitu, aya glitch leutik sejen patali jeung inaccessibility of Lokalisasi disusun. Tim LOCPATH=/tmp lokal -a bakal masihan daptar sadaya lokal di lokal-arsip, Tapi kalayan set variabel LOCPATH pikeun sakabéh program (kaasup paling lokal) lokal ieu moal sadia.
$> 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 comparisonkacindekan
Upami anjeun programmer anu biasa mikir yén string mangrupikeun sakumpulan bait, teras pilihan anjeun LC_COLLATE=C.
Upami anjeun ahli basa atanapi kompiler kamus, maka anjeun langkung saé nyusun dina lokal anjeun.
Upami anjeun pangguna saderhana, maka anjeun ngan ukur kedah biasa kanyataan yén paréntahna ls -a file outputs dimimitian ku titik dicampurkeun jeung file dimimitian ku hurup, jeung Panglima Tengah wengi, anu ngagunakeun fungsi internalna pikeun nyortir nami, nempatkeun file anu dimimitian ku titik dina awal daptar.
rujukan
sumber: www.habr.com
