Linux'тун сорттору саптарды кантип сорттойт

тааныштыруу

Мунун баары дарек маалыматын бириктирүү керек болгон кыска скрипт менен башталды электрондук почта Кадрлар бөлүмүнүн маалымат базасынан алынган кызматкерлердин кызмат орундары менен почта тизмесин колдонуучулардын тизмесинен алынган кызматкерлер. Эки тизме тең Юникод текст файлдарына экспорттолду UTF-8 жана Unix сызык аягы менен сакталган.

көрүү mail.txt

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

көрүү buhg.txt

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

Биригүү үчүн файлдар Unix буйругу менен иреттелген түрү жана Unix программасынын киргизүүсүнө берилген кошулуу, күтүлбөгөн жерден ката менен ишке ашпай калды:

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

Сорттоо жыйынтыгын өз көзүңүз менен көрүү, жалпысынан сорттоо туура экенин көрсөттү, бирок эркек жана аял фамилиялары дал келген учурда аялдар эркектерден мурун келет:

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

Юникоддогу сорттоо катасы же сорттоо алгоритминдеги феминизмдин көрүнүшү окшойт. Биринчиси, албетте, ишеничтүү.

Келгиле, аны азырынча кийинкиге калтыралы кошулуу жана көңүл буруу түрү. Келгиле, илимий покингдин жардамы менен маселени чечүүгө аракет кылалы. Биринчиден, жергиликтүү тилди өзгөртөлү en_US боюнча ru_RU. Сорттоо үчүн чөйрө өзгөрмөсүн коюу жетиштүү болмок LC_COLLATE, бирок биз майда-чүйдө нерселерге убакыт коротпойбуз:

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

Эч нерсе өзгөргөн жок.

Келгиле, файлдарды бир байттык коддоштурууга кайра коддоого аракет кылалы:

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

Кайра эч нерсе өзгөргөн жок.

Эч нерсе кыла албайсыз, интернеттен чечим издешиңиз керек. Орус фамилиялары жөнүндө түздөн-түз эч нерсе жок, бирок башка сорттоо боюнча суроолор бар. Мисалы, бул жерде бир көйгөй бар: unix сорту '-' (сызыкча) символдорду көрүнбөгөн катары карайт. Кыскасы, “а-б”, “аа”, “ac” саптары “аа”, “а-б”, “ac” болуп иргелет.

Жооп бардык жерде стандарттуу: программисттин тилин колдонуңуз "C" жана сен бактылуу болосуң. Келгиле, аракет кылалы:

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

Бир нерсе өзгөрдү. Йолкина бир жерден тайгаланып кетсе да Ивановдор туура иретте тизилип калышты. Баштапкы маселеге кайрылып көрөлү:

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

Интернет убада кылгандай, катасыз иштеген. Бул биринчи катарда Йолкина карабастан.

Көйгөй чечилди окшойт, бирок, башка орусча коддоону - Windows колдонуп көрөлү CP1251:

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

Сорттоо натыйжасы, таң калыштуусу, жергиликтүү тилге дал келет "C", жана бүт мисал, ошого жараша, катасыз иштейт. Кандайдыр бир мистика.

Мен программалоодо мистицизмди жактырбайм, анткени ал адатта каталарды жаап салат. Биз анын кантип иштээрин олуттуу карап чыгышыбыз керек. түрү жана ал эмнеге таасир этет? LC_COLLATE .

Аягында мен суроолорго жооп берүүгө аракет кылам:

  • эмне үчүн аял фамилиялары туура эмес иреттелген?
  • эмне үчүн LANG=ru_RU.CP1251 барабар болуп чыкты LANG=C
  • эмне үчүн түрү и кошулуу сорттолгон саптардын тартиби жөнүндө ар кандай ойлор
  • эмне үчүн менин бардык мисалдарымда каталар бар?
  • Акыры, саптарды өзүңүзгө жаккан кантип иреттөө керек

Юникоддо сорттоо

Биринчи аялдама №10 техникалык отчет болот Юникодду салыштыруу алгоритми сайтта unicode.org. Докладда бир топ техникалык деталдар камтылган, ошондуктан негизги ойлорду кыскача баяндап берейин.

бүтүмүн — «салыштыруу» саптар ар кандай сорттоо алгоритминин негизи болуп саналат. Алгоритмдердин өзү ар кандай болушу мүмкүн («көбүктүн», «бириктирүү», «тез»), бирок алардын баары пайда болуу тартибин аныктоо үчүн жуп саптарды салыштырууну колдонушат.

Табигый тилде саптарды сорттоо өтө татаал маселе. Эң жөнөкөй бир байт коддоодо да, алфавиттеги тамгалардын тартиби, атүгүл англис латын алфавитинен кандайдыр бир жол менен айырмаланып, бул тамгалар коддолгон сандык маанилердин тартиби менен дал келбейт. Ошентип, немис алфавитинде тамга Ö ортосунда турат О и P, жана коддоодо CP850 ал ортосунда калат ÿ и Ü.

Сиз белгилүү бир коддоодон абстракциялоого аракет кылып, Юникоддо жасалгандай, кандайдыр бир тартипте тизилген "идеалдуу" тамгаларды карап көрүңүз. Коддоштуруулар UTF8, UTF16 же бир байт KOI8-R (эгерде Юникоддун чектелген топтому керек болсо) тамгалардын ар кандай сандык көрүнүштөрүн берет, бирок базалык таблицанын ошол эле элементтерине кайрылат.

Көрсө, символдук таблицаны нөлдөн курсак да, ага универсалдуу символдук тартипти ыйгара албайбыз. Бир эле тамгаларды колдонгон ар кандай улуттук алфавиттерде бул тамгалардын тартиби ар кандай болушу мүмкүн. Мисалы, француз тилинде Æ лигатура катары каралат жана сап катары сорттолот AE. Норвег тилинде Æ кийин жайгашкан өзүнчө кат болот Z. Баса, сыяктуу лигатуралардан тышкары Æ Бир нече символдор менен жазылган тамгалар бар. Ошентип, чех алфавитинде тамга бар Ch, ортосунда турат H и I.

Алфавиттеги айырмачылыктардан тышкары сорттоого таасир эткен башка улуттук салттар бар. Тактап айтканда, суроо туулат: чоң жана кичине тамгалардан турган сөздөр сөздүктө кандай тартипте болушу керек? Сорттоого тыныш белгилерин колдонуу да таасир этиши мүмкүн. Испан тилинде суроо сүйлөмдүн башында тескери суроо белгиси колдонулат (Сиз музыканы жакшы көрөсүзбү?). Бул учурда суроо сүйлөмдөрдү алфавиттин сыртында өзүнчө кластерге топтобостон, башка тыныш белгилери бар саптарды кантип иреттөө керек экени көрүнүп турат?

Мен европалык тилдерден такыр башкача тилдердеги саптарды иретке салууга токтолбойм. Оңдон солго же өйдөдөн ылдыйга жазуу багыты бар тилдерде саптардагы символдор окуу тартибинде сакталат, ал тургай алфавиттик эмес жазуу системаларында да саптарды белги боюнча иреттөөнүн өз жолдору бар экенин эске алыңыз. . Мисалы, иероглифтер стили боюнча иреттелиши мүмкүн (Кытай тамгаларынын баскычтары) же айтылышы боюнча. Чынын айтсам, эмодзилерди кантип жайгаштыруу керек экенин билбейм, бирок силер да алар үчүн бир нерсе ойлоп тапсаңар болот.

Жогоруда саналган өзгөчөлүктөрдүн негизинде, Юникод таблицаларынын негизинде саптарды салыштыруу үчүн негизги талаптар түзүлгөн:

  • саптарды салыштыруу код таблицасында символдордун абалына көз каранды эмес;
  • бир символду түзгөн символдордун ырааттуулугу канондук формага келтирилет (A + үстүнкү тегерек менен бирдей Å);
  • Саптарды салыштырганда символ саптын контекстинде каралат жана керек болсо анын кошуналары менен бир салыштыруу бирдигине бириктирилет (Ch чех тилинде) же бир нечеге бөлүнөт (Æ Французча);
  • бардык улуттук өзгөчөлүктөр (алфавит, чоң/кичи тамга, пунктуация, жазуу түрлөрүнүн тартиби) тартипти (эмодзилерди) кол менен ыйгарууга чейин конфигурацияланышы керек;
  • салыштыруу сорттоо үчүн гана эмес, башка көптөгөн жерлерде да маанилүү, мисалы, катар диапазондорун көрсөтүү үчүн ({A... z} ордуна Баш);
  • салыштыруу абдан тез жүргүзүлүшү керек.

Мындан тышкары, отчеттун авторлору алгоритмдерди иштеп чыгуучулар таянбашы керек болгон салыштыруу касиеттерин түзүшкөн:

  • салыштыруу алгоритми ар бир тил үчүн символдордун өзүнчө топтомун талап кылбашы керек (орус жана украин тилдеринде кирилл тамгаларынын көбү колдонулат);
  • салыштыруу Юникод таблицаларындагы символдордун тартибине таянбашы керек;
  • саптын салмагы саптын атрибуту болбошу керек, анткени ар кандай маданий контексттерде бир эле сап ар кандай салмакка ээ болушу мүмкүн;
  • саптын салмагы биригүү же бөлүү учурунда өзгөрүшү мүмкүн ( x < y муну ээрчибейт xz < yz);
  • бирдей салмактагы ар кандай саптар сорттоо алгоритминин көз карашы боюнча бирдей деп эсептелет. Мындай саптарды кошумча иретке келтирүүнү киргизүү мүмкүн, бирок бул көрсөткүчтү начарлатышы мүмкүн;
  • Кайталап сорттоо учурунда бирдей салмактагы катарларды алмаштырууга болот. Бекемдик сапты салыштыруу алгоритминин касиети эмес, белгилүү бир сорттоо алгоритминин касиети (мурунку абзацты караңыз);
  • Сорттоо эрежелери убакыттын өтүшү менен өзгөрүшү мүмкүн, анткени маданий салттар такталган/өзгөрүлгөн.

Ошондой эле, салыштыруу алгоритми иштетилип жаткан саптардын семантикасы жөнүндө эч нерсе билбестиги белгиленген. Ошентип, сандардан гана турган саптарды сандар менен салыштырууга болбойт, ал эми англисче аталыштардын тизмесинде макала (Битлз, The).

Бардык көрсөтүлгөн талаптарды канааттандыруу үчүн көп деңгээлдүү (чындыгында төрт деңгээлдүү) таблицаларды сорттоо алгоритми сунушталат.

Мурда саптагы символдор канондук формага түшүрүлүп, салыштыруу бирдиктерине топтоштурулган. Салыштыруунун ар бир бирдигине бир нече салыштыруу деңгээлине туура келген бир нече салмактар ​​ыйгарылат. Салыштыруу бирдиктеринин салмактары – көп же азыраак салыштырууга мүмкүн болгон иреттелген көптүктөрдүн элементтери (бул учурда бүтүн сандар). Өзгөчө маани КАБЫЛ АЛГАН (0x0) тиешелүү салыштыруу деңгээлинде бул бирдик салыштырууга катышпайт дегенди билдирет. Саптарды салыштыруу тиешелүү деңгээлдердеги салмактарды колдонуу менен бир нече жолу кайталанышы мүмкүн. Ар бир деңгээлде эки катардын салыштыруу бирдиктеринин салмагы бири-бири менен ырааттуу түрдө салыштырылат.

Ар кандай улуттук салттар үчүн алгоритмди ар кандай ишке ашырууда коэффициенттердин маанилери ар кандай болушу мүмкүн, бирок Юникод стандарты салмактардын негизги таблицасын камтыйт - "Демейки Unicode Collation Elements Table" (DUCET). Мен өзгөрмө орнотууну белгилегим келет LC_COLLATE чындыгында сапты салыштыруу функциясында салмак таблицасын тандоонун көрсөткүчү болуп саналат.

Салмактык коэффициенттер DUCET төмөнкүдөй уюштурулган:

  • биринчи деңгээлде бардык тамгалар бир регистрге кыскартылат, диакритика алынып салынат, тыныш белгилери (баары эмес) этибарга алынбайт;
  • экинчи деңгээлде диакритика гана эске алынат;
  • үчүнчү деңгээлде бир гана жагдай эске алынат;
  • төртүнчү деңгээлде тыныш белгилери гана эске алынат.

Салыштыруу бир нече өтүүдө жүрөт: биринчиден, биринчи деңгээлдеги коэффициенттер салыштырылат; эгерде салмактар ​​дал келсе, анда экинчи даражадагы салмактар ​​менен кайталап салыштыруу жүргүзүлөт; анда балким үчүнчү жана төртүнчүсү.

Салыштыруу саптар ар кандай салмактагы салыштыруу бирдиктерин камтыганда аяктайт. Бардык төрт деңгээлде бирдей салмакка ээ катарлар бири-бирине барабар деп эсептелет.

Бул алгоритм (кошумча техникалык деталдардын бир тутам менен) №10 отчеттун аталышын берди - "Юникодду салыштыруу алгоритми" (БАУ).

Бул биздин мисалдагы сорттоо жүрүм-туруму бир аз айкыныраак болот. Аны Юникод стандарты менен салыштырса жакшы болмок.

Ишке ашырууларды сыноо үчүн БАУ атайын бар текшерүү, колдонуу салмактар ​​файлы, ишке ашыруу DUCET. Тараза файлынан ар кандай күлкүлүү нерселерди таба аласыз. Мисалы, махжонг жана европалык доминолордун тартиби, ошондой эле карталардын палубасында костюмдардын тартиби бар (символ 1F000 жана андан ары). Карточка костюмдары көпүрөнүн эрежелери боюнча жайгаштырылат - PCBT, ал эми костюмдагы карталар Т, 2,3, XNUMX... К ыраатта.

Кол менен катарлардын туура иреттелгендигин текшерүү DUCET абдан тажатма болмок, бирок, бактыга жараша, биз үчүн Юникод менен иштөө үчүн китепкананын үлгүлүү ишке ашыруу бар - "Юникод үчүн эл аралык компоненттер"(ICU).

Бул китепкананын сайтында иштелип чыккан IBM, анын ичинде демо баракчалар бар сапты салыштыруу алгоритм барагы. Биз тест линияларыбызды демейки жөндөөлөр менен киргизебиз жана мына, биз орусча сорттоодо эң сонун болуп калдык.

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

Баса, сайт ICU Тыныш белгилерин иштетүүдө салыштыруу алгоритминин тактоосун таба аласыз. Мисалдарда Салыштыруу FAQ апостроф жана дефис этибарга алынбайт.

Юникод бизге жардам берди, бирок кызыктай жүрүм-турумдун себептерин изде түрү в Linux башка жакка барууга туура келет.

glibcде сорттоо

Пайдалуу программанын булак коддорун тез көрүү түрү чейин GNU Core Utils утилитанын өзүндө локализация өзгөрмөнүн учурдагы маанисин басып чыгарууга чейин келерин көрсөттү LC_COLLATE мүчүлүштүктөрдү оңдоо режиминде иштеп жатканда:

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

Саптарды салыштыруу стандарттык функциянын жардамы менен аткарылат strcoll, бул кызыктуу нерселердин баары китепканада дегенди билдирет glibc.

боюнча Магазин долбоору glibc сапты салыштырууга арналган бир абзац. Бул абзацтан төмөнкүнү түшүнүүгө болот glibc сорттоо бизге мурунтан эле белгилүү болгон алгоритмге негизделген БАУ (Юникодду салыштыруу алгоритми) жана/же ага жакын стандартта ISO 14651 (Эл аралык сап тартиби жана салыштыруу). Акыркы стандартка карата, бул сайтта экенин белгилей кетүү керек standards.iso.org ISO 14651 расмий түрдө жалпыга жеткиликтүү деп жарыяланган, бирок тиешелүү шилтеме жок баракка алып барат. Google жүз еврого стандарттын электрондук көчүрмөсүн сатып алууну сунуш кылган расмий сайттарга шилтемелер менен бир нече барактарды кайтарат, бирок издөө натыйжаларынын үчүнчү же төртүнчү бетинде түз шилтемелер да бар. PDF. Жалпысынан алганда, стандарт дээрлик айырмаланбайт БАУ, бирок саптарды иреттөөнүн улуттук өзгөчөлүктөрүнүн ачык мисалдары жок болгондуктан окуу кызыксызыраак.

боюнча эң кызыктуу маалыматтар Магазин шилтемеси бар болчу мүчүлүштүктөрдү көзөмөлдөөчү жылы сап салыштыруу ишке ашыруу талкуулоо менен glibc. Талкуудан муну билсе болот glibc саптарды салыштыруу үчүн колдонулат ISOжеке үстөл Жалпы шаблон таблицасы (CTT), дарегин арыздан тапса болот A стандарт ISO 14651. 2000-жылдан 2015-жылга чейин бул таблицада glibc тейлөөчүсү болгон эмес жана стандарттын учурдагы версиясынан бир топ айырмаланган (жок дегенде сырткы). 2015-жылдан 2018-жылга чейин таблицанын жаңы версиясына ыңгайлашуу болуп өттү, эми сизде чыныгы жашоодо столдун жаңы версиясы менен таанышууга мүмкүнчүлүк бар (CentOS 8) жана эски (CentOS 7).

Эми биз алгоритм жана көмөкчү таблицалар жөнүндө бардык маалыматка ээ болгондон кийин, биз баштапкы маселеге кайрылып, орус тилинде саптарды кантип туура иреттөө керектигин түшүнө алабыз.

ISO 14651 / 14652

Бизди кызыктырган таблицанын баштапкы коду CTT көпчүлүк бөлүштүрүү боюнча Linux каталогдо турат /usr/share/i18n/locales/. Таблица өзү файлда iso14651_t1_common. Андан кийин бул файл директивасы iso14651_t1_common көчүрүү файлга киргизилген iso14651_t1, бул өз кезегинде улуттук файлдарга, анын ичинде en_US и ru_RU. Көпчүлүк бөлүштүрүүдө Linux бардык булак файлдары негизги орнотууга камтылган, бирок алар жок болсо, бөлүштүрүүдөн кошумча пакетти орнотууга туура келет.

Файл структурасы iso14651_t1 аттар куруу үчүн ачык-айкын эмес эрежелери менен, өтө кылдат сезилиши мүмкүн, бирок аны карап, анда баары абдан жөнөкөй. структурасы стандартта сүрөттөлгөн ISO 14652, анын көчүрмөсүн веб-сайттан жүктөп алууга болот open-std.org. Файл форматынын дагы бир сүрөттөлүшүн окууга болот спецификациялар POSIX от OpenGroup. Стандартты окууга альтернатива катары, сиз функциянын баштапкы кодун изилдей аласыз биргелешип_окуу в glibc/locale/programs/ld-collate.c.

Файлдын структурасы төмөнкүдөй көрүнөт:

Демейки боюнча, символ качуу символу катары колдонулат жана # символунан кийинки саптын аягы комментарий болуп саналат. Эки символду тең кайра аныктоого болот, бул жадыбалдын жаңы версиясында аткарылган:

escape_char /
comment_char %

Файл форматтагы токендерди камтыйт же (Кайда x - он алтылык сан). Бул коддоодогу Юникод кодунун чекиттеринин он алтылык өкүлчүлүгү UCS-4 (UTF-32). Бардык башка элементтер бурчтуу кашаалардагы (анын ичинде , <2> жана ушул сыяктуулар) контексттен тышкаркы мааниге ээ болгон жөнөкөй сап константалары болуп эсептелет.

Сап LC_COLLATE кийинки саптарды салыштырууну сүрөттөгөн маалыматтар башталат деп айтат.

Биринчиден, салыштыруу таблицасындагы салмактар ​​үчүн аттар жана символдордун айкалыштары үчүн аттар көрсөтүлөт. Жалпысынан алганда, аталыштардын эки түрү эки башка объектке таандык, бирок иш жүзүндө алар аралашкан. Салмактардын аттары ачкыч сөз менен белгиленет жыйноо белгиси (салыштыруу белгиси), анткени салыштыруу учурунда бирдей салмакка ээ болгон Юникод символдору эквиваленттүү белгилер болуп эсептелет.

Учурдагы файлды кайра карап чыгуудагы бөлүмдүн жалпы узундугу 900 сапка жакын. Аттардын ээнбаштыгын жана синтаксистин бир нече түрлөрүн көрсөтүү үчүн бир нече жерден мисал тарттым.

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

  • жыйноо белгиси сапты жазат ОСМАНЯ таразалардын аталыштарынын таблицасында
  • жыйноо белгиси .. префикстен турган ысымдардын ырааттуулугун каттайт S жана он алтылык сандык суффикс тартып 1D000 үчүн 1D35F.
  • фффф в жыйноо белгиси он алтылык санда чоң белгиси жок бүтүн санга окшош, бирок бул жөн гана аты окшош болушу мүмкүн
  • ысым коддоодо коддук чекитти билдирет UCS-4
  • чогултуучу элемент ""ден Юникод чекиттеринин жупунун жаңы аталышын каттайт.

Салмактардын аттары аныкталгандан кийин, чыныгы салмактар ​​көрсөтүлөт. Салыштырууда чоңдуктан азыраак мамилелер гана маанилүү болгондуктан, салмактар ​​листингдин жөнөкөй ырааттуулугу менен аныкталат. Адегенде "жеңил" салмактар, андан кийин "оорураак" салмактар ​​келтирилет. Эске сала кетейин, ар бир Юникод символуна төрт түрдүү салмак ыйгарылган. Бул жерде алар бир иреттелген ырааттуулукка бириктирилет. Теориялык жактан алганда, каалаган каймана ат төрт деңгээлдин каалаганында колдонулушу мүмкүн, бирок комментарийлер иштеп чыгуучулар ысымдарды психикалык жактан деңгээлдерге бөлөрүн көрсөтүп турат.

% 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

Акыр-аягы, чыныгы салмак таблицасы.

Салмактар ​​бөлүмү ачкыч сөз саптарында камтылган буйрук_баштоо и order_end. Кошумча опциялар буйрук_баштоо салыштыруунун ар бир деңгээлинде кайсы багытта саптар сканерленгенин аныктаңыз. демейки жөндөө болуп саналат алдыга. Бөлүмдүн корпусу символдук кодду жана анын төрт салмагын камтыган саптардан турат. Символдун коду символдун өзү, код чекити же мурда аныкталган символдук ат менен көрсөтүлүшү мүмкүн. Салмактар ​​символдук аттарга, коддук чекиттерге же символдордун өзүнө да берилиши мүмкүн. Эгерде код чекиттери же символдор колдонулса, алардын салмагы коддук чекиттин сандык маанисине барабар болот (Юникод таблицасындагы орду). Ачык көрсөтүлбөгөн символдор (мен түшүнгөндөй) Юникод таблицасындагы позицияга дал келген негизги салмагы менен таблицага дайындалган деп эсептелет. Өзгөчө салмак мааниси КӨҢҮЛДҮРБӨ салыштыруунун тиешелүү деңгээлинде символдун этибарга алынбай калганын билдирет.

Таразанын түзүлүшүн көрсөтүү үчүн мен үч айкын үзүндүнү тандап алдым:

  • такыр этибарга алынбаган каармандар
  • алгачкы эки деңгээлдеги үч санына барабар белгилер
  • кириллица алфавитинин башталышы, анда диакритика жок, ошондуктан негизинен биринчи жана үчүнчү деңгээлдер боюнча иргелет.

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

Эми сиз макаланын башынан баштап мисалдарды сорттоого кайта аласыз. Буктурма салмактар ​​таблицанын бул бөлүгүндө жайгашкан:

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

Бул таблицада тыныш белгилери таблицадан алынганын көрүүгө болот ASCII (анын ичинде боштук) саптарды салыштырганда дээрлик дайыма этибарга алынбайт. Бир гана өзгөчөлүктөр - дал келген позициялардагы тыныш белгилеринен башка бардык нерсеге дал келген саптар. Салыштыруу алгоритми үчүн менин мисалымдагы саптар (сорттоодон кийин) төмөнкүдөй көрүнөт:

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

Тараза таблицасында орус тилиндеги баш тамгалар кичине тамгалардан кийин келерин эске алсак (үчүнчү деңгээлде) караганда оор ), сорттоо таптакыр туура көрүнөт.

Өзгөрмө орнотууда LC_COLLATE=C байт-байт салыштырууну көрсөткөн атайын таблица жүктөлөт

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'
};

Юникоддо Ё код чекити Адан мурун келгендиктен, саптар ошого жараша иргелет.

Тексттик жана бинардык таблицалар

Албетте, саптарды салыштыруу өтө кеңири таралган операция жана таблицаны талдоо CTT абдан кымбат процедура. Таблицага жетүүнү оптималдаштыруу үчүн, ал команда менен экилик формага түзүлөт localdef.

команда localdef параметр катары улуттук мүнөздөмөлөрдүн таблицасы бар файлды кабыл алат (вариант -i), мында бардык символдор Юникод чекиттери менен көрсөтүлөт жана Юникод чекиттери менен белгилүү бир коддоонун символдорунун ортосундагы кат алышуу файлы (вариант) -f). Жумуштун натыйжасында акыркы параметрде көрсөтүлгөн аталыш менен тил үчүн бинардык файлдар түзүлөт.

glibc эки бинардык файл форматтарын колдойт: "салттуу" жана "заманбап".

Салттуу формат тилдин аталышы ички каталогдун аты экенин билдирет /usr/lib/locale/. Бул подкаталог экилик файлдарды сактайт LC_COLLATE, LC_CTYPE, LC_TIME жана башка. Файл LC_IDENTIFICATION жергиликтүү тилдин расмий аталышын (каталогдун аталышынан башкача болушу мүмкүн) жана комментарийлерди камтыйт.

Заманбап формат бардык тилдерди бир архивде сактоону камтыйт /usr/lib/locale/locale-archive, колдонулган бардык процесстердин виртуалдык эс тутумуна түшүрүлгөн glibc. Заманбап форматтагы тил аты айрым канонизацияга дуушар болот - коддоо аттарында кичине тамгага кыскартылган сандар жана тамгалар гана калат. Ошентип ru_RU.KOI8-R, катары сакталат ru_RU.koi8r.

Киргизилген файлдар учурдагы каталогдо, ошондой эле каталогдордо изделет /usr/share/i18n/locales/ и /usr/share/i18n/charmaps/ файлдар үчүн CTT жана тиешелүүлүгүнө жараша файлдарды коддоо.

Мисалы, буйрук

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

файлды түзөт /usr/share/i18n/locales/ru_RU коддоо файлын колдонуу /usr/share/i18n/charmaps/MAC-CYRILLIC.gz жана натыйжаны сактаңыз /usr/lib/locale/locale-archive аты менен ru_RU.maccyrillic

Эгер сиз өзгөрмө орнотсоңуз Lang = en_US.UTF-8 жана glibc төмөнкү файлдардын жана каталогдордун ырааттуулугунда жергиликтүү экилик файлдарды издейт:

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

Эгерде жергиликтүү тил салттуу жана заманбап форматта болсо, анда заманбап форматка артыкчылык берилет.

Сиз буйрук менен түзүлгөн тилдердин тизмесин көрө аласыз сабы -a.

Салыштыруу таблицасын даярдоо

Эми, билим менен куралданган, сиз өзүңүздүн идеалдуу саптарды салыштыруу таблицаңызды түзө аласыз. Бул таблица орус тамгаларын, анын ичинде Ё тамгасын туура салыштырып, ошол эле учурда таблицага ылайык тыныш белгилерин эске алышы керек. ASCII.

Өзүңүздүн сорттоо таблицаңызды даярдоо процесси эки этаптан турат: салмактык таблицаны түзөтүү жана буйрук менен бинардык формага компиляциялоо. localdef.

Салыштыруу таблицасы форматта минималдуу түзөтүү чыгымдары менен жөнгө салынышы үчүн ISO 14652 Учурдагы таблицанын салмагын жөнгө салуу үчүн бөлүмдөр берилген. Бөлүм ачкыч сөз менен башталат кайра иреттөө жана алмаштыруу аткарылгандан кийин кызмат ордун көрсөтүү менен. Бөлүм сызык менен аяктайт кайра иреттөө. Эгерде таблицанын бир нече бөлүмдөрүн оңдоо зарыл болсо, анда ар бир мындай бөлүм үчүн бөлүм түзүлөт.

Мен файлдардын жаңы версияларын көчүрдүм iso14651_t1_common и ru_RU репозиторийден glibc менин үй каталогума ~/.local/share/i18n/locales/ жана бөлүмдү бир аз түзөттү LC_COLLATE в ru_RU. Файлдардын жаңы версиялары менин версиям менен толук шайкеш келет glibc. Эгерде сиз файлдардын эски версияларын колдонгуңуз келсе, таблицадагы символдук аталыштарды жана алмаштыруу башталган жерди өзгөртүүгө туура келет.

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

Чынында, бул талааларды өзгөртүү керек болмок LC_IDENTIFICATION Ошентип, алар жергиликтүү аймакты көрсөтүп турат ru_MY, бирок менин мисалымда бул талап кылынган жок, анткени мен архивди жергиликтүү тилдерди издөөдөн чыгарып салдым жергиликтүү архив.

ошол localdef өзгөрмө аркылуу менин папкамдагы файлдар менен иштедим I18NPATH Киргизүү файлдарын издөө үчүн кошумча каталогду кошо аласыз, ал эми бинардык файлдарды сактоо каталогун сызыктар менен жол катары көрсөтүүгө болот:

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

POSIX ичинде деп болжолдойт ЖЫЛА локалдык файлдары бар каталогдорго абсолюттук жолдорду алдыга сызыктан баштап жаза аласыз, бирок glibc в Linux бардык жолдор негизги каталогдон эсептелет, аны өзгөрмө аркылуу жокко чыгарууга болот LOCPATH. Орнотуудан кийин LOCPATH=~/.local/lib/locale/ локализацияга байланыштуу бардык файлдар менин папкамда гана изделет. Өзгөрмөлөр топтому менен тилдердин архиви LOCPATH этибарга алынбаган.

Бул жерде чечүүчү сыноо болуп саналат:

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

Жашасын! Биз жасадык!

Каталардын үстүнөн иштөө

Мен башында берилген саптарды сорттоо боюнча суроолорго жооп бердим, бирок каталар жөнүндө дагы бир нече суроолор бар - көрүнөө жана көрүнбөгөн.

Баштапкы маселеге кайрылып көрөлү.

Жана программа түрү жана программа кошулуу бир эле сапты салыштыруу функцияларын колдонуңуз glibc. Кантип ушундай болуп калды кошулуу буйругу менен иреттелген саптарда сорттоо катасын берди түрү жергиликтүү тилде en_US.UTF-8? Жооп жөнөкөй: түрү бүт сапты салыштырат, жана кошулуу демейки боюнча биринчи боштук белгисине чейин саптын башталышы болгон ачкычты гана салыштырат. Менин мисалымда бул ката билдирүүсүнө алып келди, анткени саптардагы биринчи сөздөрдүн сорттору толук саптардын сортторуна дал келген жок.

Жергиликтүү "C" сорттолгон саптарда биринчи боштукка чейинки баштапкы субсаптар да иреттелээрине кепилдик берет, бирок бул катаны гана жашырат. Ката билдирүүсүз файлдарды бириктирүү туура эмес натыйжа бере турган маалыматтарды (фамилиялары бирдей, бирок аттары башка адамдарды) тандоого болот. Биз кааласак кошулуу толук аты менен бириктирилген файл саптары, анда туура жол талаа бөлгүчтү ачык көрсөтүү жана бүт сап боюнча эмес, ачкыч талаасы боюнча сорттоо болот. Бул учурда, бириктирүү туура жүрөт жана эч бир тилде каталар болбойт:

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

Коддоштуруу боюнча ийгиликтүү аткарылган мисал CP1251 башка ката камтыйт. Чындыгында мага белгилүү болгон бардык бөлүштүрүүлөрдө Linux пакеттерде компиляцияланган тил жок ru_RU.CP1251. Эгерде компиляцияланган тил табылбаса, анда түрү унчукпай байт-байт салыштырууну колдонот, биз байкаган нерсе.

Баса, компиляцияланган тилдердин жеткиликсиздигине байланыштуу дагы бир кичинекей ката бар. Команда LOCPATH=/tmp locale -a бардык аймактардын тизмесин берет жергиликтүү архив, бирок өзгөрмөлөр топтому менен LOCPATH бардык программалар үчүн (анын ичинде көпчүлүгү жергиликтүү) бул тилдер жеткиликтүү болбойт.

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

жыйынтыктоо

Эгерде сиз саптар байттардын жыйындысы деп ойлоп көнгөн программист болсоңуз, анда сиздин тандооңуз LC_COLLATE=C.

Эгерде сиз лингвист же сөздүк түзүүчү болсоңуз, анда өз тилиңизде түзүңүз.

Эгер сиз жөнөкөй колдонуучу болсоңуз, анда сиз жөн гана буйрукка көнүшүңүз керек дар -a тамга менен башталган файлдар менен аралашкан чекиттен башталган файлдарды чыгарат жана Түн ортосунда командир, аталыштарды иреттөө үчүн өзүнүн ички функцияларын колдонгон, тизменин башына чекит менен башталган файлдарды коёт.

шилтемелер

Отчет №10 Юникодду салыштыруу алгоритми

Unicode.org дарегиндеги каармандардын салмагы

ICU — IBM компаниясынан Юникод менен иштөө үчүн китепкананы ишке ашыруу.

Сорттоо тестин колдонуу ICU

Каармандардын салмагы ISO 14651

Файл форматынын масштабы менен сүрөттөлүшү ISO 14652

Саптарды салыштыруу боюнча талкуу glibc

Source: www.habr.com

Комментарий кошуу