{"id":83055,"date":"2020-05-28T01:42:15","date_gmt":"2020-05-27T23:42:15","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/kak-linuxovskij-sort-sortiruet-stroki"},"modified":"2020-05-28T01:42:15","modified_gmt":"2020-05-27T23:42:15","slug":"kak-linuxovskij-sort-sortiruet-stroki","status":"publish","type":"post","link":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/kak-linuxovskij-sort-sortiruet-stroki","title":{"rendered":"Comment sort de Linux trie les cha\u00eenes","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<h1 id=\"vvedenie\">Introduction<\/h1>\n<p><\/p>\n<p>Tout a commenc\u00e9 par un script court, cens\u00e9 combiner les informations sur les adresses <em>e-mail<\/em> des employ\u00e9s, obtenues \u00e0 partir de la liste des utilisateurs de la newsletter, avec les postes des employ\u00e9s, obtenus \u00e0 partir de la base des ressources humaines. Les deux listes ont \u00e9t\u00e9 export\u00e9es dans des fichiers texte en codage Unicode <em>UTF-8<\/em> et sauvegard\u00e9es avec des fins de ligne unixiennes.<\/p>\n<p><\/p>\n<p>Contenu <em>mail.txt<\/em><\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Ivanov Andre\u00ef;ia@example.com<\/code><\/pre>\n<p><\/p>\n<p>Contenu <em>buhg.txt<\/em><\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Ivanova Alla;peintre\nYelkina Ella;gruti\u00e8re\nIvanov Andre\u00ef;ouvrier\nAbakanov Mikha\u00efl;peintre<\/code><\/pre>\n<p><\/p>\n<p>Pour combiner, les fichiers ont \u00e9t\u00e9 tri\u00e9s avec la commande unixienne <em>sort<\/em> et donn\u00e9s en entr\u00e9e \u00e0 un programme unixien <em>joindre<\/em>, qui s'est termin\u00e9 de mani\u00e8re inattendue avec une erreur : <\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; sort buhg.txt &gt; buhg.srt\n$&gt; sort mail.txt &gt; mail.srt\n$&gt; join buhg.srt mail.srt &gt; result\njoin: buhg.srt:4: n'est pas tri\u00e9: Ivanov Andre\u00ef;ouvrier<\/code><\/pre>\n<p><\/p>\n<p>Un aper\u00e7u du r\u00e9sultat du tri a montr\u00e9 qu'en g\u00e9n\u00e9ral le tri \u00e9tait correct, mais en cas de co\u00efncidences entre les noms masculins et f\u00e9minins, les f\u00e9minins sont plac\u00e9s avant les masculins :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; sort buhg.txt\nAbakanov Mikha\u00efl;peintre\nYelkina Ella;gruti\u00e8re\nIvanova Alla;peintre\nIvanov Andre\u00ef;ouvrier<\/code><\/pre>\n<p><\/p>\n<p>Cela ressemble \u00e0 un bug de tri en Unicode ou \u00e0 une manifestation du f\u00e9minisme dans l'algorithme de tri. La premi\u00e8re explication est bien s\u00fbr plus plausible.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Mettons cela de c\u00f4t\u00e9 pour l'instant <em>joindre<\/em> et concentrons-nous sur <em>sort<\/em>. Tentons de r\u00e9soudre le probl\u00e8me par t\u00e2tonnements. Pour commencer, changeons la locale de <em>en_US<\/em> sur <em>ru_RU<\/em>. Pour le tri, il suffirait de d\u00e9finir la variable d'environnement <em>LC_COLLATE<\/em>, mais nous n'allons pas faire les choses \u00e0 moiti\u00e9 :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; LANG=ru_RU.UTF-8 sort buhg.txt\nAbakanov Mikha\u00efl;peintre\nYelkina Ella;gruti\u00e8re\nIvanova Alla;peintre\nIvanov Andre\u00ef;ouvrier<\/code><\/pre>\n<p><\/p>\n<p>Rien n'a chang\u00e9.<\/p>\n<p><\/p>\n<p>Essayons de re-coder les fichiers en une seule octet : <\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; iconv -f UTF-8 -t KOI8-R buhg.txt \n | LANG=ru_RU.KOI8-R sort \n | iconv -f KOI8-R -t UTF8<\/code><\/pre>\n<p><\/p>\n<p>Encore rien n'a chang\u00e9.<\/p>\n<p><\/p>\n<p>Il n'y a rien \u00e0 faire, il va falloir chercher une solution sur Internet. Rien de particulier sur les noms russes, mais il y a des questions sur d'autres bizarreries du tri. Par exemple, voici un tel probl\u00e8me : <noindex><a rel=\"nofollow\" href=\"https:\/\/serverfault.com\/questions\/95579\/unix-sort-treats-dash-characters-as-invisible\/95593\">Le tri Unix consid\u00e8re les caract\u00e8res '-' (tiret) comme invisibles<\/a><\/noindex>. En r\u00e9sum\u00e9, les cha\u00eenes \"a-b\", \"aa\", \"ac\" sont tri\u00e9es comme \"aa\", \"a-b\", \"ac\".<\/p>\n<p><\/p>\n<p>La r\u00e9ponse est toujours la m\u00eame : utilisez la locale programmer <em>\"C\"<\/em> et vous serez heureux. Essayons :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; LANG=C sort buhg.txt\nYelkina Ella;gruti\u00e8re\nAbakanov Mikha\u00efl;peintre\nIvanov Andre\u00ef;ouvrier\nIvanova Alla;avocate<\/code><\/pre>\n<p><\/p>\n<p>Il y a quelque chose qui a chang\u00e9. Les Ivanov se sont rang\u00e9s dans le bon ordre, mais Yelkina a disparu quelque part. Revenons \u00e0 la t\u00e2che initiale :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; LANG=C sort buhg.txt &gt; buhg.srt\n$&gt; LANG=C sort mail.txt &gt; mail.srt\n$&gt; LANG=C join buhg.srt mail.srt &gt; result<\/code><\/pre>\n<p><\/p>\n<p>\u00c7a a fonctionn\u00e9 sans erreurs, tout comme l'a promis Internet. Et ce, malgr\u00e9 Yolkine \u00e0 la premi\u00e8re ligne.<\/p>\n<p><\/p>\n<p>Le probl\u00e8me semble r\u00e9solu, mais pour \u00eatre s\u00fbr, essayons une autre codage en russe \u2014 celui de Windows. <em>CP1251<\/em>:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; iconv -f UTF-8 -t CP1251 buhg.txt \n | LANG=ru_RU.CP1251 sort \n | iconv -f CP1251 -t UTF8 <\/code><\/pre>\n<p><\/p>\n<p>Le r\u00e9sultat du tri, \u00e9trangement, co\u00efncidera avec la locale. <em>\"C\"<\/em>, et tout l'exemple, en cons\u00e9quence, se d\u00e9roule sans erreurs. C'est quelque chose de mystique.<\/p>\n<p><\/p>\n<p>Je n'aime pas la mystique en programmation, car elle dissimule g\u00e9n\u00e9ralement des erreurs. Je vais devoir m'occuper s\u00e9rieusement de la fa\u00e7on dont les choses fonctionnent. <em>sort<\/em> et de ce \u00e0 quoi cela influence. <em>LC_COLLATE<\/em> .<\/p>\n<p><\/p>\n<p>\u00c0 la fin, j'essaierai de r\u00e9pondre aux questions :<\/p>\n<p><\/p>\n<ul>\n<li>pourquoi les noms de famille des femmes n'\u00e9taient pas tri\u00e9s correctement.<\/li>\n<li>pourquoi <em>LANG=ru_RU.CP1251<\/em> s'est av\u00e9r\u00e9 \u00e9quivalent. <em>LANG=C<\/em><\/li>\n<li>pourquoi il y a <em>sort<\/em> et <em>joindre<\/em> des repr\u00e9sentations diff\u00e9rentes de l'ordre des cha\u00eenes tri\u00e9es.<\/li>\n<li>pourquoi il y a des erreurs dans tous mes exemples.<\/li>\n<li>enfin, comment trier les cha\u00eenes selon ses propres go\u00fbts.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"sortirovka-v-yunikode\">Le tri en Unicode.<\/h1>\n<p><\/p>\n<p>Premier arr\u00eat, le rapport technique n\u00b0 10 intitul\u00e9 <noindex><a rel=\"nofollow\" href=\"https:\/\/unicode.org\/reports\/tr10\/\">algorithme de collation Unicode.<\/a><\/noindex> sur le site <noindex><a rel=\"nofollow\" href=\"https:\/\/unicode.org\">unicode.org<\/a><\/noindex>. Le rapport contient de nombreux d\u00e9tails techniques, donc je vais me permettre de donner un r\u00e9sum\u00e9 des id\u00e9es principales.<\/p>\n<p><\/p>\n<p><em>Collation<\/em> \u2014 La \"comparaison\" des cha\u00eenes est la base de tout algorithme de tri. Les algorithmes eux-m\u00eames peuvent varier (\"bulles\", \"fusion\", \"rapide\"), mais tous effectueront une comparaison de paires de cha\u00eenes pour d\u00e9terminer l'ordre de leur succession.<\/p>\n<p><\/p>\n<p>Le tri des cha\u00eenes en langue naturelle est un probl\u00e8me assez complexe. M\u00eame dans les encodages \u00e0 un octet les plus simples, l'ordre des lettres dans un alphabet, m\u00eame s'il diff\u00e8re quelque peu de l'alphabet latin anglais, ne co\u00efncide d\u00e9j\u00e0 plus avec l'ordre des valeurs num\u00e9riques par lesquelles ces lettres sont encod\u00e9es. Par exemple, dans l'alphabet allemand, la lettre <em>\u00d6<\/em> se situe entre <em>O<\/em> et <em>redicted Frame)<\/em>, et dans l'encodage <em>CP850<\/em> elle se trouve entre <em>\u00ff<\/em> et <em>\u00dc.<\/em>.<\/p>\n<p><\/p>\n<p>On peut tenter de s'abstraire de l'encodage sp\u00e9cifique et de consid\u00e9rer les \"lettres id\u00e9ales\" dispos\u00e9es dans un certain ordre, comme cela est fait dans Unicode. Les encodages <em>UTF8<\/em>, <em>UTF16<\/em> ou un octet <em>KOI8-R<\/em> (si un sous-ensemble limit\u00e9 d'Unicode est n\u00e9cessaire) donneront diff\u00e9rentes repr\u00e9sentations num\u00e9riques des lettres, mais feront r\u00e9f\u00e9rence aux m\u00eames \u00e9l\u00e9ments de la table de base. <\/p>\n<p><\/p>\n<p>Il s'av\u00e8re que m\u00eame en construisant une table de caract\u00e8res \u00e0 partir de z\u00e9ro, nous ne pourrons pas \u00e9tablir un ordre universel pour les caract\u00e8res. Dans diff\u00e9rents alphabets nationaux utilisant les m\u00eames lettres, l'ordre de ces lettres peut varier. Par exemple, en fran\u00e7ais, <em>\u00c6<\/em> sera consid\u00e9r\u00e9 comme une ligature et tri\u00e9 comme une cha\u00eene. <em>AE<\/em>Dans la langue norv\u00e9gienne, <em>\u00c6<\/em> sera une lettre \u00e0 part, qui se place apr\u00e8s <em>Z<\/em>. D'ailleurs, en plus des ligatures comme <em>\u00c6<\/em> il existe des lettres \u00e9crites avec plusieurs symboles. Ainsi, dans l'alphabet tch\u00e8que, il y a la lettre <em>Ch<\/em>, qui se situe entre <em>H<\/em> et <em>I<\/em>.<\/p>\n<p><\/p>\n<p>En plus des diff\u00e9rences dans les alphabets, il existe d'autres traditions nationales qui influencent le tri. En particulier, une question se pose : dans quel ordre doivent appara\u00eetre dans un dictionnaire les mots compos\u00e9s de lettres majuscules et minuscules ? De plus, la mani\u00e8re dont la ponctuation est utilis\u00e9e peut \u00e9galement influencer le tri. En espagnol, un point d'interrogation invers\u00e9 est plac\u00e9 au d\u00e9but d'une phrase interrogative (<em>\u00bfTe gusta la m\u00fasica ?<\/em>). Dans ce cas, il est clair que les phrases interrogatives ne doivent pas \u00eatre regroup\u00e9es dans un cluster s\u00e9par\u00e9 en dehors de l'alphabet, mais comment trier les cha\u00eenes avec d'autres signes de ponctuation ?<\/p>\n<p><\/p>\n<p>Je ne vais pas m'attarder sur le tri des cha\u00eenes dans des langues tr\u00e8s diff\u00e9rentes des europ\u00e9ennes. Je noterai que dans les langues ayant une orientation d'\u00e9criture de droite \u00e0 gauche ou de haut en bas, les symboles dans les cha\u00eenes sont probablement stock\u00e9s dans l'ordre de lecture, et m\u00eame dans des \u00e9critures non alphab\u00e9tiques, il existe des moyens propres d'organiser les cha\u00eenes par caract\u00e8re. Par exemple, les id\u00e9ogrammes peuvent \u00eatre class\u00e9s selon leur trac\u00e9 (<noindex><a rel=\"nofollow\" href=\"https:\/\/studychinese.ru\/kljuchi\/\">les cl\u00e9s des id\u00e9ogrammes chinois<\/a><\/noindex>) ou selon leur prononciation. Je ne sais pas comment les \u00e9mojis devraient \u00eatre class\u00e9s, mais il doit y avoir quelque chose \u00e0 en dire.<\/p>\n<p><\/p>\n<p>Sur la base des particularit\u00e9s \u00e9num\u00e9r\u00e9es ci-dessus, les principales exigences comparatives pour les cha\u00eenes bas\u00e9es sur les tables Unicode ont \u00e9t\u00e9 formul\u00e9es :<\/p>\n<p><\/p>\n<ul>\n<li>la comparaison des cha\u00eenes ne d\u00e9pend pas de la position des caract\u00e8res dans le tableau de codes ;<\/li>\n<li>les s\u00e9quences de caract\u00e8res formant un seul caract\u00e8re sont ram\u00e9n\u00e9es \u00e0 leur forme canonique (<em>A<\/em> + un cercle sup\u00e9rieur est le m\u00eame que <em>\u00c5<\/em>);<\/li>\n<li>lors de la comparaison de cha\u00eenes, le caract\u00e8re est consid\u00e9r\u00e9 dans le contexte de la cha\u00eene et, si n\u00e9cessaire, est combin\u00e9 avec des voisines en une seule unit\u00e9 de comparaison (<em>Ch<\/em> en tch\u00e8que) ou est divis\u00e9 en plusieurs (<em>\u00c6<\/em> en fran\u00e7ais);<\/li>\n<li>Toutes les particularit\u00e9s nationales (alphabet, majuscules\/minuscules, ponctuation, ordre des types d'\u00e9criture) doivent \u00eatre configur\u00e9es jusqu'\u00e0 la d\u00e9signation manuelle de l'ordre (emoji);<\/li>\n<li>La comparaison est importante non seulement pour le tri, mais aussi dans de nombreux autres contextes, par exemple pour d\u00e9finir des plages de lignes (substitution {A... \u044f} dans <em>bash<\/em>);<\/li>\n<li>la comparaison doit \u00eatre effectu\u00e9e suffisamment rapidement.<\/li>\n<\/ul>\n<p><\/p>\n<p>De plus, les auteurs du rapport ont formul\u00e9 des propri\u00e9t\u00e9s de comparaison sur lesquelles les d\u00e9veloppeurs d'algorithmes ne doivent pas compter :<\/p>\n<p><\/p>\n<ul>\n<li>l'algorithme de comparaison ne doit pas n\u00e9cessiter un ensemble distinct de caract\u00e8res pour chaque langue (les langues russe et ukrainienne partagent la plupart des caract\u00e8res cyrilliques);<\/li>\n<li>la comparaison ne doit pas se fonder sur l'ordre des caract\u00e8res dans les tableaux Unicode;<\/li>\n<li>le poids de la cha\u00eene ne doit pas \u00eatre un attribut de la cha\u00eene, car une m\u00eame cha\u00eene peut avoir des poids diff\u00e9rents dans diff\u00e9rents contextes culturels;<\/li>\n<li>les poids des cha\u00eenes peuvent changer lors de fusions ou de divisions (de <em>x<\/em> &lt; <em>y<\/em> il ne s'ensuit pas que <em>xz<\/em> &lt; <em>yz<\/em>);<\/li>\n<li>des cha\u00eenes diff\u00e9rentes ayant des poids identiques sont consid\u00e9r\u00e9es comme \u00e9gales du point de vue de l'algorithme de tri. L'introduction d'un ordre suppl\u00e9mentaire pour ces cha\u00eenes est possible, mais cela pourrait d\u00e9grader les performances;<\/li>\n<li>lors de tris r\u00e9p\u00e9t\u00e9s, les cha\u00eenes ayant des poids identiques peuvent \u00e9changer leurs places. La stabilit\u00e9 est une propri\u00e9t\u00e9 d'un algorithme de tri particulier, et non d'un algorithme de comparaison de cha\u00eenes (voir point pr\u00e9c\u00e9dent);<\/li>\n<li>les r\u00e8gles de tri peuvent changer au fil du temps \u00e0 mesure que les traditions culturelles se pr\u00e9cisent\/changent.<\/li>\n<\/ul>\n<p><\/p>\n<p>Il est \u00e9galement stipul\u00e9 que l'algorithme de comparaison ne conna\u00eet rien de la s\u00e9mantique des cha\u00eenes trait\u00e9es. Ainsi, les cha\u00eenes compos\u00e9es uniquement de chiffres ne doivent pas \u00eatre compar\u00e9es comme des nombres, et dans les listes de noms anglais, l'article ne doit pas \u00eatre supprim\u00e9 (<em>Beatles, The<\/em>).<\/p>\n<p><\/p>\n<p>Pour satisfaire toutes les exigences \u00e9nonc\u00e9es, un algorithme de tri en plusieurs niveaux (quatre niveaux en fait) est propos\u00e9.<\/p>\n<p><\/p>\n<p>Au pr\u00e9alable, les caract\u00e8res de la cha\u00eene sont mis sous une forme canonique et regroup\u00e9s en unit\u00e9s de comparaison. \u00c0 chaque unit\u00e9 de comparaison sont attribu\u00e9s plusieurs poids, correspondant \u00e0 diff\u00e9rents niveaux de comparaison. Les poids des unit\u00e9s de comparaison sont des \u00e9l\u00e9ments d'ensembles ordonn\u00e9s (dans ce cas, des entiers), qui peuvent \u00eatre compar\u00e9s entre eux. Une valeur sp\u00e9ciale <em>IGNORED<\/em> (0x0) signifie qu'\u00e0 ce niveau de comparaison, cette unit\u00e9 ne participe pas \u00e0 la comparaison. La comparaison des cha\u00eenes peut \u00eatre r\u00e9p\u00e9t\u00e9e plusieurs fois, en utilisant les poids des niveaux correspondants. \u00c0 chaque niveau, les poids des unit\u00e9s de comparaison des deux cha\u00eenes sont compar\u00e9s les uns aux autres.<\/p>\n<p><\/p>\n<p>Dans diff\u00e9rentes r\u00e9alisations de l'algorithme pour diff\u00e9rentes traditions nationales, les valeurs des coefficients peuvent diff\u00e9rer, mais le standard Unicode comprend un tableau de poids de base - <em>\"Table d'\u00c9l\u00e9ments de Coliation Unicode par D\u00e9faut\"<\/em> (<em>DUCET<\/em>). Je tiens \u00e0 souligner que l'\u00e9tablissement de la variable <em>LC_COLLATE<\/em> est en fait une indication du choix du tableau de poids dans la fonction de comparaison de cha\u00eenes.<\/p>\n<p><\/p>\n<p>Les coefficients de poids <em>DUCET<\/em> sont organis\u00e9s comme suit :<\/p>\n<p><\/p>\n<ul>\n<li>au premier niveau, toutes les lettres sont mises en minuscule, les signes diacritiques sont ignor\u00e9s, et la plupart des signes de ponctuation sont ignor\u00e9s;<\/li>\n<li>au deuxi\u00e8me niveau, seuls les signes diacritiques sont pris en compte;<\/li>\n<li>au troisi\u00e8me niveau, seul le registre est pris en compte;<\/li>\n<li>au quatri\u00e8me niveau, seuls les signes de ponctuation sont pris en compte.<\/li>\n<\/ul>\n<p><\/p>\n<p>La comparaison se fait en plusieurs passes : d'abord, les coefficients du premier niveau sont compar\u00e9s ; si les poids correspondent, une comparaison r\u00e9p\u00e9t\u00e9e est effectu\u00e9e avec les poids du deuxi\u00e8me niveau ; puis, \u00e9ventuellement, ceux du troisi\u00e8me et du quatri\u00e8me.<\/p>\n<p><\/p>\n<p>La comparaison se termine lorsque des unit\u00e9s de comparaison correspondantes avec des poids diff\u00e9rents se trouvent dans les cha\u00eenes. Les cha\u00eenes ayant des poids \u00e9gaux \u00e0 tous les quatre niveaux sont consid\u00e9r\u00e9es comme \u00e9gales entre elles.<\/p>\n<p><\/p>\n<p>Cet algorithme (avec plein de d\u00e9tails techniques suppl\u00e9mentaires) a donn\u00e9 son nom au rapport n\u00b0 10 - <em>\"Algorithme de Coliation Unicode\"<\/em> (<em>UCA<\/em>).<\/p>\n<p><\/p>\n<p>\u00c0 ce stade, le comportement de tri de notre exemple devient un peu plus clair. Il serait bon de le comparer au standard Unicode.<\/p>\n<p><\/p>\n<p>Pour tester les r\u00e9alisations <em>UCA<\/em> il existe un <noindex><a rel=\"nofollow\" href=\"https:\/\/www.unicode.org\/Public\/UCA\/latest\/CollationTest.html\">test<\/a><\/noindex>, utilisant <noindex><a rel=\"nofollow\" href=\"http:\/\/www.unicode.org\/Public\/UCA\/latest\/allkeys.txt\">un fichier de poids<\/a><\/noindex>, impl\u00e9mentant <em>DUCET<\/em>. Dans le fichier de poids, on peut trouver diff\u00e9rentes curiosit\u00e9s. Par exemple, il y a l'ordre des tuiles de Mahjong et du domino europ\u00e9en, ainsi que l'ordre des couleurs dans un jeu de cartes (symbole <em>1F000<\/em> et au-del\u00e0). Les couleurs des cartes sont dispos\u00e9es selon les r\u00e8gles du bridge - PCHBT, et les cartes de chaque couleur sont dans l'ordre T,2,3\u2026 K.<\/p>\n<p><\/p>\n<p>Une v\u00e9rification manuelle de la validit\u00e9 du tri des cha\u00eenes selon <em>DUCET<\/em> serait plut\u00f4t fatigante, mais heureusement pour nous, il existe une r\u00e9alisation exemplaire de biblioth\u00e8que pour travailler avec Unicode \u2014 \"<noindex><a rel=\"nofollow\" href=\"http:\/\/site.icu-project.org\/\">International Components for Unicode<\/a><\/noindex>\" (<em>ICU<\/em>).<\/p>\n<p><\/p>\n<p>Sur le site de cette biblioth\u00e8que, d\u00e9velopp\u00e9e \u00e0 <em>IBM<\/em>, il y a des pages de d\u00e9monstration, y compris une <noindex><a rel=\"nofollow\" href=\"http:\/\/demo.icu-project.org\/icu-bin\/collation.html\">page d'algorithme de comparaison de cha\u00eenes<\/a><\/noindex>. Nous introduisons nos cha\u00eenes de test avec les param\u00e8tres par d\u00e9faut et, oh miracle, nous obtenons un tri russe parfait.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Abakanov Mikha\u00efl;peintre\nYolkina Ella;gruti\u00e8re\nIvanov Andre\u00ef;ouvrier\nIvanova Alla;avocat<\/code><\/pre>\n<p><\/p>\n<p>Au fait, sur le site <em>ICU<\/em> on peut trouver des pr\u00e9cisions sur le fonctionnement de l'algorithme de comparaison lors du traitement des signes de ponctuation. Dans les exemples <noindex><a rel=\"nofollow\" href=\"http:\/\/userguide.icu-project.org\/collation\/faq\">Collation FAQ<\/a><\/noindex> l'apostrophe et le trait d'union sont ignor\u00e9s.<\/p>\n<p><\/p>\n<p>Unicode nous a aid\u00e9s, mais il faudra chercher les raisons du comportement \u00e9trange <em>sort<\/em> dans <em>Linux<\/em> ailleurs.<\/p>\n<p><\/p>\n<h1 id=\"sortirovka-v-glibc\">Tri dans glibc<\/h1>\n<p><\/p>\n<p>Un aper\u00e7u rapide du code source de l'outil <em>sort<\/em> de <em>GNU Core Utils<\/em> a montr\u00e9 que dans l'outil, la localisation se limite \u00e0 l'impression de la valeur actuelle de la variable <em>LC_COLLATE<\/em> lors de l'ex\u00e9cution en mode d\u00e9bogage :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$ sort --debug buhg.txt &gt; buhg.srt\nsort: utilisant les r\u00e8gles de tri \u2018en_US.UTF8\u2019<\/code><\/pre>\n<p><\/p>\n<p>La comparaison de cha\u00eenes est effectu\u00e9e par la fonction standard <em>strcoll<\/em>, donc tout ce qui est int\u00e9ressant se trouve dans la biblioth\u00e8que <em>glibc<\/em>.<\/p>\n<p><\/p>\n<p>Sur <em>wiki<\/em> du projet <em>glibc<\/em> qui est d\u00e9di\u00e9e \u00e0 la comparaison de cha\u00eenes <noindex><a rel=\"nofollow\" href=\"https:\/\/sourceware.org\/glibc\/wiki\/Locales#LC_COLLATE\">un paragraphe<\/a><\/noindex>. De ce paragraphe, on peut comprendre que dans <em>glibc<\/em> le tri est bas\u00e9 sur l'algorithme d\u00e9j\u00e0 connu <em>UCA<\/em> (<em>The Unicode collation algorithm<\/em>) et\/ou sur la norme proche <em>ISO 14651<\/em> (<em>Ordonnancement et comparaison des cha\u00eenes internationales<\/em>). En ce qui concerne la derni\u00e8re norme, il convient de noter qu'elle est annonc\u00e9e officiellement comme publique sur le site <noindex><a rel=\"nofollow\" href=\"https:\/\/standards.iso.org\/ittf\/PubliclyAvailableStandards\">standards.iso.org<\/a><\/noindex> <em>ISO 14651<\/em> , mais le lien correspondant m\u00e8ne \u00e0 une page inexistante. Google donne plusieurs pages avec des liens vers des sites officiels qui proposent d'acheter une copie \u00e9lectronique de la norme pour une centaine d'euros, mais \u00e0 la troisi\u00e8me ou quatri\u00e8me page des r\u00e9sultats de recherche, vous trouverez aussi des liens directs vers <em>PDF<\/em>. En g\u00e9n\u00e9ral, la norme ne diff\u00e8re pratiquement pas de <em>UCA<\/em>, mais est plus ennuyeuse \u00e0 lire car elle ne contient pas d'exemples frappants des particularit\u00e9s nationales de l'ordre des cha\u00eenes. <\/p>\n<p><\/p>\n<p>L'information la plus int\u00e9ressante sur <em>wiki<\/em> s'est r\u00e9v\u00e9l\u00e9e \u00eatre un lien vers <noindex><a rel=\"nofollow\" href=\"https:\/\/sourceware.org\/bugzilla\/show_bug.cgi?id=14095\">le tracker de bogues<\/a><\/noindex> avec des discussions sur la mise en \u0153uvre de la comparaison de cha\u00eenes dans <em>glibc<\/em>. D'une discussion, on peut apprendre qu'\u00e0 <em>glibc<\/em> la comparaison de cha\u00eenes utilise <em>ISO<\/em>un tableau <noindex><a rel=\"nofollow\" href=\"http:\/\/www.iso.org\/ittf\/ISO14651_2006_TABLE1_en.txt\">The Common Template Table<\/a><\/noindex> (<em>CTT<\/em>), dont l'adresse peut \u00eatre trouv\u00e9e dans l'annexe <em>A<\/em> de la norme <em>ISO 14651<\/em>. Entre 2000 et 2015, ce tableau a <em>glibc<\/em> n'avait pas de mainteneur et diff\u00e9rait suffisamment (du moins visuellement) de la version actuelle de la norme. De 2015 \u00e0 2018, une adaptation \u00e0 la nouvelle version du tableau a eu lieu et \u00e0 l'heure actuelle, vous avez la chance de rencontrer dans la vie r\u00e9elle \u00e0 la fois la nouvelle version du tableau (<em>CentOS 8<\/em>), et l'ancienne (<em>CentOS 7<\/em>). <\/p>\n<p><\/p>\n<p>Maintenant que nous avons toutes les informations sur l'algorithme et les tableaux auxiliaires, nous pouvons revenir \u00e0 la probl\u00e9matique initiale et comprendre comment trier correctement les lignes dans la locale russe.<\/p>\n<p><\/p>\n<h1 id=\"iso-1465114652\">ISO 14651\/14652<\/h1>\n<p><\/p>\n<p>Le code source du tableau qui nous int\u00e9resse <em>CTT<\/em> se trouve dans la plupart des distributions <em>Linux<\/em> dans le r\u00e9pertoire <em>\/usr\/share\/i18n\/locales\/<\/em>. Le tableau lui-m\u00eame se trouve dans le fichier <em>iso14651_t1_common<\/em>. Ce fichier est ensuite inclus dans le fichier <em>copy iso14651_t1_common<\/em> qui, \u00e0 son tour, est inclus dans les fichiers nationaux, y compris dans <em>. Dans la plupart des distributions<\/em>tous les fichiers sources sont inclus dans l'installation de base, mais s'ils ne sont pas pr\u00e9sents, il faudra installer un paquet suppl\u00e9mentaire de la distribution. <em>en_US<\/em> et <em>ru_RU<\/em>peut sembler horriblement verbeux, avec des r\u00e8gles de construction de noms peu \u00e9videntes, mais une fois que vous comprenez, tout est assez simple. La structure est d\u00e9crite dans la norme <em>Linux<\/em> ISO 14652<\/p>\n<p><\/p>\n<p>Structure du fichier <em>. Dans la plupart des distributions<\/em> , dont une copie peut \u00eatre t\u00e9l\u00e9charg\u00e9e sur le site <em>open-std.org<\/em>. Une autre description du format de fichier peut \u00eatre lue dans les <noindex><a rel=\"nofollow\" href=\"http:\/\/www.open-std.org\/JTC1\/SC22\/WG20\/docs\/n972-14652ft.pdf\">sp\u00e9cifications<\/a><\/noindex>OpenGroup <noindex><a rel=\"nofollow\" href=\"https:\/\/pubs.opengroup.org\/onlinepubs\/9699919799\/basedefs\/V1_chap07.html\">. En alternative \u00e0 la lecture de la norme, vous pouvez \u00e9tudier le code source de la fonction<\/a><\/noindex> <em>POSIX<\/em> \u00e0 partir de <em>collate_read<\/em>glibc\/locale\/programs\/ld-collate.c <em>La structure du fichier est la suivante :<\/em> dans <em>Par d\u00e9faut, le caract\u00e8re  est utilis\u00e9 comme caract\u00e8re d'\u00e9chappement, et la fin de la ligne apr\u00e8s le caract\u00e8re # est un commentaire. Les deux caract\u00e8res peuvent \u00eatre red\u00e9finis, ce qui a \u00e9t\u00e9 fait dans la nouvelle version du tableau :<\/em>.<\/p>\n<p><\/p>\n<p>escape_char \/\ncomment_char %<\/p>\n<p><\/p>\n<p>Dans le fichier, vous rencontrerez des jetons au format<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">escape_char \/\\ncomment_char %<\/code><\/pre>\n<p><\/p>\n<p>Le fichier contiendra des jetons au format <em>(o\u00f9<\/em> ou <em>est un chiffre hexad\u00e9cimal). Cette repr\u00e9sentation hexad\u00e9cimale des points de code Unicode est en codage<\/em> UCS-4 <em>x<\/em> UTF-32 <em>). Tous les autres \u00e9l\u00e9ments entre crochets (y compris<\/em> (<em>UTF-32<\/em>). Tous les autres \u00e9l\u00e9ments entre crochets (y compris <em>et similaires), sont consid\u00e9r\u00e9s comme des constantes de cha\u00eene simples, n'ayant pas de signification particuli\u00e8re en dehors du contexte.<\/em>, <em>nous indique que les donn\u00e9es d\u00e9crivant la comparaison des cha\u00eenes commencent.<\/em> Tout d'abord, des noms sont d\u00e9finis pour les poids dans le tableau de comparaison et des noms pour les combinaisons de caract\u00e8res. En g\u00e9n\u00e9ral, deux types de noms appartiennent \u00e0 deux entit\u00e9s diff\u00e9rentes, mais dans un fichier r\u00e9el, ils sont m\u00e9lang\u00e9s. Les noms des poids sont d\u00e9finis par le mot-cl\u00e9<\/p>\n<p><\/p>\n<p>Cha\u00eene <em>LC_COLLATE<\/em> collating-symbol<\/p>\n<p><\/p>\n<p>Tout d'abord, les noms des poids dans le tableau de comparaison et les noms des combinaisons de caract\u00e8res sont d\u00e9finis. En g\u00e9n\u00e9ral, deux types de noms appartiennent \u00e0 deux entit\u00e9s diff\u00e9rentes, mais dans le fichier r\u00e9el, ils sont m\u00e9lang\u00e9s. Les noms des poids sont d\u00e9finis par le mot cl\u00e9 <em>collating-symbol<\/em> (symbole de comparaison), car lors de la comparaison, les caract\u00e8res Unicode ayant le m\u00eame poids seront consid\u00e9r\u00e9s comme des caract\u00e8res \u00e9quivalents.<\/p>\n<p><\/p>\n<p>La longueur totale de la section dans la r\u00e9vision actuelle du fichier est d'environ 900 lignes. J'ai extrait des exemples de plusieurs endroits pour montrer l'arbitraire des noms et quelques types de syntaxe.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">LC_COLLATE\n\ncollating-symbol \ncollating-symbol \ncollating-symbol \ncollating-symbol \n...\ncollating-symbol \ncollating-symbol \ncollating-symbol \n...\ncollating-symbol ..\ncollating-symbol  % Valeur de symbole garantie la plus grande. Gardez \u00e0 la fin de cette liste\n...\ncollating-element  from \"\"\ncollating-element  from \"\"<\/code><\/pre>\n<p><\/p>\n<ul>\n<li><em>collating-symbol<\/em> enregistre une cha\u00eene <em>OSMANYA<\/em> dans le tableau des noms de poids <\/li>\n<li><em>collating-symbol ..<\/em> enregistre une s\u00e9quence de noms, compos\u00e9e d'un pr\u00e9fixe <em>S<\/em> et d'un suffixe num\u00e9rique hexad\u00e9cimal allant de <em>1D000<\/em> \u00e0 <em>1D35F<\/em>.<\/li>\n<li><em>FFFF<\/em> dans <em>collating-symbol<\/em> appara\u00eet comme un grand entier non sign\u00e9 en notation hexad\u00e9cimale, mais <em>&lt;SFFFF&gt;<\/em> c'est juste un nom qui pourrait ressembler \u00e0 <em>&lt;VERYBIGVAL&gt;<\/em> <\/li>\n<li>nom <em>&lt;U0413&gt;<\/em> repr\u00e9sente un point de code dans l'encodage <em>). Tous les autres \u00e9l\u00e9ments entre crochets (y compris<\/em><\/li>\n<li><em>collating-element  from \"\"<\/em> enregistre un nouveau nom pour une paire de points Unicode. <\/li>\n<\/ul>\n<p><\/p>\n<p>Lorsque les noms des poids sont d\u00e9finis, les poids eux-m\u00eames sont assign\u00e9s. Puisque lors de la comparaison seul le rapport sup\u00e9rieur-inf\u00e9rieur compte, les poids sont d\u00e9termin\u00e9s par une simple s\u00e9quence d'\u00e9num\u00e9ration des noms. Les poids les plus \"l\u00e9gers\" sont \u00e9num\u00e9r\u00e9s en premier, suivis des poids les plus \"lourds\". Je vous rappelle que chaque symbole Unicode se voit attribuer quatre poids diff\u00e9rents. Ici, ils sont regroup\u00e9s en une seule s\u00e9quence ordonn\u00e9e. Th\u00e9oriquement, n'importe quel nom symbolique peut \u00eatre utilis\u00e9 \u00e0 n'importe quel des quatre niveaux, mais les commentaires indiquent que les d\u00e9veloppeurs ont en t\u00eate de diviser mentalement les noms par niveaux.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">% Attributions de poids symboliques\n\n% Attributions de poids de troisi\u00e8me niveau\n\n\n\n\n...\n% Attributions de poids de deuxi\u00e8me niveau\n\n % COMBINING LOW LINE\n % COMBINING COMMA ABOVE\n % COMBINING REVERSED COMMA ABOVE\n...\n% Attributions de poids de premier niveau\n % TABULATION HORIZONTALE\n % RETOUR \u00c0 LA LIGNE\n % TABULATION VERTICALE\n...\n % LETTRE MINUSCULE CYRILIQUE DE\n % LETTRE MINUSCULE CYRILIQUE KOMI DE\n % LETTRE MINUSCULE CYRILIQUE DJE\n % LETTRE MINUSCULE CYRILIQUE KOMI DJE\n % LETTRE MINUSCULE CYRILIQUE GJE\n % LETTRE MINUSCULE CYRILIQUE ZE AVEC DESCENDEUR\n % LETTRE MINUSCULE CYRILIQUE IE\n % LETTRE MINUSCULE CYRILIQUE IE AVEC BR\u00c8VE\n % LETTRE MINUSCULE CYRILIQUE IE UKRAINIENNE\n % LETTRE MINUSCULE CYRILIQUE ZHE<\/code><\/pre>\n<p><\/p>\n<p>Enfin, le tableau des poids.<\/p>\n<p><\/p>\n<p>La section des poids est encapsul\u00e9e dans des lignes avec des mots-cl\u00e9s <em>order_start<\/em> et <em>order_end<\/em>. Des param\u00e8tres suppl\u00e9mentaires <em>order_start<\/em> d\u00e9terminent dans quelle direction les lignes sont parcourues \u00e0 chaque niveau de comparaison. Par d\u00e9faut, le param\u00e8tre <em>forward<\/em>. Le corps de la section est compos\u00e9 de lignes contenant le code du caract\u00e8re et ses quatre poids. Le code du caract\u00e8re peut \u00eatre repr\u00e9sent\u00e9 par le symbole lui-m\u00eame, le point de code ou un nom symbolique d\u00e9fini auparavant. Les poids peuvent \u00e9galement \u00eatre sp\u00e9cifi\u00e9s par des noms symboliques, des points de code ou les symboles eux-m\u00eames. Si des points de code ou des symboles sont utilis\u00e9s, leur poids correspond \u00e0 la valeur num\u00e9rique du point de code (position dans la table Unicode). Les symboles non sp\u00e9cifi\u00e9s explicitement (tel que je le comprends) sont consid\u00e9r\u00e9s comme ayant un poids primaire correspondant \u00e0 leur position dans la table Unicode. La valeur sp\u00e9ciale du poids <em>IGNORE<\/em> indique qu'\u00e0 ce niveau de comparaison, ce caract\u00e8re est ignor\u00e9.<\/p>\n<p><\/p>\n<p>Pour d\u00e9montrer la structure des poids, j'ai choisi trois extraits assez \u00e9vidents :<\/p>\n<p><\/p>\n<ul>\n<li>les symboles qui sont compl\u00e8tement ignor\u00e9s<\/li>\n<li>les symboles \u00e9quivalents au chiffre trois aux deux premiers niveaux<\/li>\n<li>le d\u00e9but de l'alphabet cyrillique, qui ne contient pas de signes diacritiques, et donc se trie principalement selon les premier et troisi\u00e8me niveaux.<\/li>\n<\/ul>\n<p><\/p>\n<pre><code class=\"plaintext\">order_start forward;forward;forward;forward,position\n IGNORE;IGNORE;IGNORE;IGNORE % NULL (dans 6429)\n IGNORE;IGNORE;IGNORE;IGNORE % D\u00c9BUT DE L'EN-T\u00caTE (dans 6429)\n IGNORE;IGNORE;IGNORE;IGNORE % D\u00c9BUT DU TEXTE (dans 6429)\n...\n ;;; % CHIFFRE TROIS\n ;;; % CHIFFRE TROIS EN LARGEUR PLEINE\n ;;; % CHIFFRE TROIS ENTRE PARENTH\u00c8SES\n ;;; % CHIFFRE TROIS POINT FINAL\n ;;<FONT>; % CHIFFRE TROIS EN GRAS MATHEMATIQUE\n...\n ;;; % LETTRE MINUSCULE CYRILLIQUE A\n ;;; % LETTRE MAJUSCULE CYRILLIQUE A\n ;;; % LETTRE MINUSCULE CYRILLIQUE A AVEC BREVE\n ;;; % LETTRE MINUSCULE CYRILLIQUE A AVEC BREVE\n...\n ;;; % LETTRE MINUSCULE CYRILLIQUE BE\n ;;; % LETTRE MAJUSCULE CYRILLIQUE BE\n ;;; % LETTRE MINUSCULE CYRILLIQUE VE\n ;;; % LETTRE MAJUSCULE CYRILLIQUE VE\n...\norder_end<\/code><\/pre>\n<p><\/p>\n<p>Il est maintenant possible de revenir \u00e0 la tri des exemples du d\u00e9but de l'article. Le pi\u00e8ge se cache dans cette partie du tableau des poids :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">IGNORE;IGNORE;IGNORE; % ESPACE\n IGNORE;IGNORE;IGNORE; % POINT D'EXCLAMATION\n IGNORE;IGNORE;IGNORE; % GUILLEMET\n...<\/code><\/pre>\n<p><\/p>\n<p>Il est \u00e9vident que dans ce tableau, la ponctuation est extraite du tableau <em>ASCII<\/em> (y compris l'espace) lors de la comparaison des cha\u00eenes, elle est presque toujours ignor\u00e9e. L'exception concerne uniquement les cha\u00eenes qui correspondent compl\u00e8tement, \u00e0 l'exception de la ponctuation apparaissant aux m\u00eames positions. Les cha\u00eenes de mon exemple (apr\u00e8s le tri) pour l'algorithme de comparaison apparaissent comme suit :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">AbakanovMikhailPeintre\nYolkinaEllaCrane\nIvanovaAllaPeintre\nIvanovAndreiSoudard<\/code><\/pre>\n<p><\/p>\n<p>\u00c9tant donn\u00e9 que dans le tableau des poids, les majuscules en russe viennent apr\u00e8s les minuscules (au troisi\u00e8me niveau <em>&lt;CAP&gt;<\/em> plus lourd que <em>&lt;MIN&gt;<\/em>), le tri appara\u00eet absolument correct.<\/p>\n<p><\/p>\n<p>Lors de la d\u00e9finition de la variable <em>LC_COLLATE=C<\/em> une table sp\u00e9ciale est charg\u00e9e, laquelle d\u00e9finit la comparaison octet par octet<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">static const uint32_t collseqwc[] =\n{\n  8, 1, 8, 0x0, 0xff,\n  \/* 1st-level table *\/\n  6 * sizeof (uint32_t),\n  \/* 2nd-level table *\/\n  7 * sizeof (uint32_t),\n  \/* 3rd-level table *\/\n  L'x00', L'x01', L'x02', L'x03', L'x04', L'x05', L'x06', L'x07',\n  L'x08', L'x09', L'x0a', L'x0b', L'x0c', L'x0d', L'x0e', L'x0f',\n\n...\n  L'xf8', L'xf9', L'xfa', L'xfb', L'xfc', L'xfd', L'xfe', L'xff'\n};<\/code><\/pre>\n<p><\/p>\n<p>\u00c9tant donn\u00e9 que dans Unicode, le point de code \u0401 se situe avant A, les cha\u00eenes sont tri\u00e9es en cons\u00e9quence.<\/p>\n<p><\/p>\n<h1 id=\"tekstovye-i-dvoichnye-tablicy\">Tables textuelles et binaires<\/h1>\n<p><\/p>\n<p>Il est \u00e9vident que la comparaison de cha\u00eenes est une op\u00e9ration extr\u00eamement fr\u00e9quente, et que l'analyse de la table <em>CTT<\/em> est une proc\u00e9dure plut\u00f4t co\u00fbteuse. Pour optimiser l'acc\u00e8s \u00e0 la table, elle est compil\u00e9e en format binaire par la commande <em>localedef<\/em>.<\/p>\n<p><\/p>\n<p>Commande <em>localedef<\/em> prend en param\u00e8tre un fichier avec la table des sp\u00e9cificit\u00e9s nationales (option <em>-i<\/em>), dans lequel tous les symboles sont repr\u00e9sent\u00e9s par des points Unicode, et un fichier de correspondance entre les points Unicode et les symboles d'un encodage sp\u00e9cifique (option <em>-f<\/em>). \u00c0 l'issue du traitement, des fichiers binaires pour la locale sont cr\u00e9\u00e9s, portant le nom sp\u00e9cifi\u00e9 dans le dernier param\u00e8tre.<\/p>\n<p><\/p>\n<p><em>Glibc<\/em> supporte deux formats de fichiers binaires : \"traditionnel\" et \"moderne\".<\/p>\n<p><\/p>\n<p>Le format traditionnel signifie que le nom de la locale est le nom d'un sous-r\u00e9pertoire dans <em>\/usr\/lib\/locale\/<\/em>. Dans ce sous-r\u00e9pertoire se trouvent les fichiers binaires <em>LC_COLLATE<\/em>, <em>LC_CTYPE<\/em>, <em>LC_TIME<\/em> etc. Le fichier <em>LC_IDENTIFICATION<\/em> contient le nom formel de la locale (qui peut diff\u00e9rer du nom du r\u00e9pertoire) et des commentaires.<\/p>\n<p><\/p>\n<p>Le format moderne suppose que toutes les locales sont stock\u00e9es dans une seule archive <em>\/usr\/lib\/locale\/locale-archive<\/em>, qui est mapp\u00e9e dans la m\u00e9moire virtuelle de tous les processus utilisant <em>glibc<\/em>Le nom de la locale au format moderne subit une certaine canonisation \u2014 dans les noms d'encodage, seuls les chiffres et les lettres restent, convertis en minuscules. Ainsi, <em>fr_FR.KOI8-R<\/em>, sera conserv\u00e9 comme <em>fr_FR.koi8r<\/em>.<\/p>\n<p><\/p>\n<p>Les fichiers d'entr\u00e9e sont recherch\u00e9s dans le r\u00e9pertoire courant, ainsi que dans les r\u00e9pertoires <em>\/usr\/share\/i18n\/locales\/<\/em> et <em>\/usr\/share\/i18n\/charmaps\/<\/em> pour les fichiers <em>CTT<\/em> et les fichiers d'encodage respectivement.<\/p>\n<p><\/p>\n<p>Par exemple, la commande<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">localedef -i fr_FR -f MAC-CYRILLIC fr_FR.MAC-CYRILLIC<\/code><\/pre>\n<p><\/p>\n<p>va compiler le fichier <em>\/usr\/share\/i18n\/locales\/ru_RU<\/em> en utilisant le fichier d'encodage <em>\/usr\/share\/i18n\/charmaps\/MAC-CYRILLIC.gz<\/em> et enregistrera le r\u00e9sultat dans <em>\/usr\/lib\/locale\/locale-archive<\/em> sous le nom <em>fr_FR.maccyrillic<\/em><\/p>\n<p><\/p>\n<p>Si la variable <em>LANG=en_US.UTF-8<\/em> alors <em>glibc<\/em> elle cherchera les fichiers binaires de locale dans la s\u00e9quence suivante de fichiers et de r\u00e9pertoires :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">\/usr\/lib\/locale\/locale-archive\n\/usr\/lib\/locale\/en_US.UTF-8\/\n\/usr\/lib\/locale\/en_US\/\n\/usr\/lib\/locale\/enUTF-8\/\n\/usr\/lib\/locale\/en\/<\/code><\/pre>\n<p><\/p>\n<p>Si la locale est pr\u00e9sente \u00e0 la fois dans les formats traditionnel et moderne, la priorit\u00e9 est donn\u00e9e au moderne.<\/p>\n<p><\/p>\n<p>Vous pouvez consulter la liste des locales compil\u00e9es avec la commande <em>locale -a<\/em>.<\/p>\n<p><\/p>\n<h1 id=\"podgotovka-svoey-tablicy-sravneniya\">Pr\u00e9paration de votre propre table de comparaison<\/h1>\n<p><\/p>\n<p>Maintenant, arm\u00e9 de vos connaissances, vous pouvez cr\u00e9er votre propre table de comparaison id\u00e9ale. Cette table doit comparer correctement les lettres russes, y compris la lettre \u0401, tout en tenant compte des signes de ponctuation selon le tableau <em>ASCII<\/em>.<\/p>\n<p><\/p>\n<p>Le processus de pr\u00e9paration de votre propre table de tri se compose de deux \u00e9tapes : l'\u00e9dition de la table des poids et sa compilation en forme binaire avec la commande <em>localedef<\/em>.<\/p>\n<p><\/p>\n<p>Pour que la table de comparaison puisse \u00eatre ajust\u00e9e avec un minimum de modifications, le format <em>open-std.org<\/em> pr\u00e9voit des sections d'ajustement des poids de la table existante. La section commence par le mot cl\u00e9 <em>reorder-after<\/em> et l'indication de la position apr\u00e8s laquelle le remplacement est effectu\u00e9. La section se termine par la ligne <em>reorder-end<\/em>. S'il est n\u00e9cessaire de corriger plusieurs parties de la table, une section est cr\u00e9\u00e9e pour chaque partie.<\/p>\n<p><\/p>\n<p>J'ai copi\u00e9 de nouvelles versions des fichiers <em>iso14651_t1_common<\/em> et <em>ru_RU<\/em> depuis le d\u00e9p\u00f4t <em>glibc<\/em> dans mon r\u00e9pertoire personnel ~\/.local\/share\/i18n\/locales\/ et j'ai l\u00e9g\u00e8rement modifi\u00e9 la section <em>LC_COLLATE<\/em> dans <em>ru_RU<\/em>. Les nouvelles versions des fichiers sont enti\u00e8rement compatibles avec ma version <em>glibc<\/em>. Si vous souhaitez utiliser les anciennes versions des fichiers, vous devrez changer les noms symboliques et l'emplacement \u00e0 partir duquel le remplacement commence dans la table.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">LC_COLLATE\n% Copiez le mod\u00e8le de l'ISO\/IEC 14651\ncopy \"iso14651_t1\"\nreorder-after \n ;;; % ESPACE\n ;;; % POINT D'EXCLAMATION\n ;;; % GUILLEMET\n...\n ;;; % ACCOLADE DROITE\n ;;; % TILDE\nreorder-end\nEND LC_COLLATE<\/code><\/pre>\n<p><\/p>\n<p>En fait, il aurait fallu changer les champs dans <em>LC_IDENTIFICATION<\/em> pour qu'ils pointent vers la locale <em>ru_MY<\/em>, mais dans mon exemple cela n'\u00e9tait pas n\u00e9cessaire, car j'ai exclu de la recherche la locale archive <em>locale-archive<\/em>.<\/p>\n<p><\/p>\n<p>Pour que <em>localedef<\/em> travaillait avec les fichiers dans mon dossier via la variable <em>I18NPATH<\/em> on peut ajouter un r\u00e9pertoire suppl\u00e9mentaire pour rechercher les fichiers d'entr\u00e9e, et le r\u00e9pertoire pour enregistrer les fichiers binaires peut \u00eatre indiqu\u00e9 comme un chemin avec des slashes :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; I18NPATH=~\/.local\/share\/i18n localedef -i ru_RU -f UTF-8 ~\/.local\/lib\/locale\/ru_MY.UTF-8<\/code><\/pre>\n<p><\/p>\n<p><em>POSIX<\/em> sous-entend que <em>LANG<\/em> on peut \u00e9crire des chemins absolus vers des r\u00e9pertoires contenant des fichiers de locale, commen\u00e7ant par un slash, mais <em>glibc<\/em> dans <em>Linux<\/em> tous les chemins sont consid\u00e9r\u00e9s par rapport au r\u00e9pertoire de base, qui peut \u00eatre red\u00e9fini via la variable <em>LOCPATH<\/em>. Apr\u00e8s avoir d\u00e9fini <em>LOCPATH=~\/.local\/lib\/locale\/<\/em> tous les fichiers li\u00e9s \u00e0 la localisation seront recherch\u00e9s uniquement dans mon dossier. L'archive de locales avec la variable d\u00e9finie <em>LOCPATH<\/em> est ignor\u00e9e.<\/p>\n<p><\/p>\n<p>Voici le test d\u00e9cisif :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; LANG=ru_MY.UTF-8 LOCPATH=~\/.local\/lib\/locale\/ sort buhg.txt\nAbakanov Mikhail;peintre\nYolkina Ella;gruti\u00e8re\nIvanov Andrei;serrurier\nIvanova Alla;avocate<\/code><\/pre>\n<p><\/p>\n<p>Hourra ! Nous l'avons fait !<\/p>\n<p><\/p>\n<h1 id=\"rabota-nad-oshibkami\">Travail sur les erreurs<\/h1>\n<p><\/p>\n<p>J'ai d\u00e9j\u00e0 r\u00e9pondu aux questions sur le tri des cha\u00eenes soulev\u00e9es au d\u00e9but, mais il reste encore quelques questions sur les erreurs \u2014 visibles et invisibles.<\/p>\n<p><\/p>\n<p>Revenons \u00e0 la t\u00e2che initiale.<\/p>\n<p><\/p>\n<p>Et le programme <em>sort<\/em> et le programme <em>joindre<\/em> utilisent les m\u00eames fonctions de comparaison de cha\u00eenes de <em>glibc<\/em>. Comment se fait-il que <em>joindre<\/em> a produit une erreur de tri sur les cha\u00eenes tri\u00e9es par la commande <em>sort<\/em> dans la locale <em>en_US.UTF-8<\/em>? \u041e\u0442\u0432\u0435\u0442 \u043f\u0440\u043e\u0441\u0442: <em>sort<\/em> compare la cha\u00eene dans son int\u00e9gralit\u00e9, tandis que <em>joindre<\/em> ne compare que la cl\u00e9, qui par d\u00e9faut est le d\u00e9but de la cha\u00eene jusqu'au premier espace. Dans mon exemple, cela a conduit \u00e0 un message d'erreur, car le tri des premiers mots des cha\u00eenes ne correspondait pas au tri des cha\u00eenes enti\u00e8res.<\/p>\n<p><\/p>\n<p>La locale <em>\"C\"<\/em> garantit que dans les cha\u00eenes tri\u00e9es, les sous-cha\u00eenes initiales jusqu'au premier espace seront \u00e9galement tri\u00e9es, mais cela ne fait que masquer l'erreur. Il est possible de s\u00e9lectionner des donn\u00e9es telles que (des personnes avec le m\u00eame nom de famille mais des pr\u00e9noms diff\u00e9rents), qui donneraient un r\u00e9sultat incorrect lors de la fusion des fichiers sans message d'erreur. Si nous voulons que <em>joindre<\/em> fusionne les cha\u00eenes des fichiers par nom complet, la bonne m\u00e9thode serait de sp\u00e9cifier explicitement le s\u00e9parateur de champs et de trier par le champ cl\u00e9, plut\u00f4t que par la cha\u00eene enti\u00e8re. Dans ce cas, la fusion se d\u00e9roulera correctement et il n'y aura pas d'erreurs dans aucune locale :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; sort -t ; -k 1 buhg.txt &gt; buhg.srt\n$&gt; sort -t ; -k 1 mail.txt &gt; mail.srt\n$&gt; join -t ; buhg.srt mail.srt &gt; result<\/code><\/pre>\n<p><\/p>\n<p>Exemple r\u00e9ussi dans l'encodage <em>CP1251<\/em> contient une autre erreur. Le fait est que dans toutes les distributions que je connais <em>Linux<\/em> les paquets manquent de locales compil\u00e9es <em>ru_RU.CP1251<\/em>. Si aucune locale compil\u00e9e n'est trouv\u00e9e, alors <em>sort<\/em> elle utilise silencieusement une comparaison au niveau des octets, ce que nous avons observ\u00e9.<\/p>\n<p><\/p>\n<p>Au fait, il y a un autre petit bug li\u00e9 \u00e0 l'indisponibilit\u00e9 des locales compil\u00e9es. La commande <em>LOCPATH=\/tmp locale -a<\/em> affichera la liste de toutes les locales dans <em>locale-archive<\/em>, mais avec la variable install\u00e9e <em>LOCPATH<\/em> pour tous les programmes (y compris la propre <em>locale<\/em>) ces locales seront inaccessibles.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; LOCPATH=\/tmp locale -a | grep en_US\nlocale : Impossible de d\u00e9finir LC_CTYPE sur la locale par d\u00e9faut : Aucun fichier ou dossier de ce type\nlocale : Impossible de d\u00e9finir LC_MESSAGES sur la locale par d\u00e9faut : Aucun fichier ou dossier de ce type\nlocale : Impossible de d\u00e9finir LC_COLLATE sur la locale par d\u00e9faut : Aucun fichier ou dossier de ce type\nen_US\nen_US.iso88591\nen_US.iso885915\nen_US.utf8\n\n$&gt; LC_COLLATE=en_US.UTF-8 sort --debug\nsort : utilisation des r\u00e8gles de tri \u2018en_US.UTF-8\u2019\n\n$&gt; LOCPATH=\/tmp LC_COLLATE=en_US.UTF-8 sort --debug\nsort : utilisation d'une simple comparaison des octets<\/code><\/pre>\n<p><\/p>\n<h1 id=\"zaklyuchenie\">Conclusion<\/h1>\n<p><\/p>\n<p>Si vous \u00eates un programmeur qui consid\u00e8re que les cha\u00eenes sont un ensemble d'octets, alors votre choix <em>LC_COLLATE=C<\/em>.<\/p>\n<p><\/p>\n<p>Si vous \u00eates linguiste ou r\u00e9dacteur de dictionnaire, il est pr\u00e9f\u00e9rable de compiler votre locale.<\/p>\n<p><\/p>\n<p>Si vous \u00eates un utilisateur ordinaire, il vous suffit de vous habituer \u00e0 ce que la commande <em>ls -a<\/em> produit des fichiers commen\u00e7ant par un point, m\u00e9lang\u00e9s avec des fichiers d\u00e9butant par une lettre, alors que <em>Midnight Commander<\/em>, qui utilise ses propres fonctions internes pour trier les noms, met les fichiers commen\u00e7ant par un point en t\u00eate de liste.<\/p>\n<p><\/p>\n<h1 id=\"ssylki\">Liens<\/h1>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/unicode.org\/reports\/tr10\/\">Rapport n\u00b010 sur l'algorithme de collation Unicode <\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"http:\/\/www.unicode.org\/Public\/UCA\/latest\/allkeys.txt\">Les poids des caract\u00e8res sur unicode.org <\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"http:\/\/userguide.icu-project.org\/intro\"><em>ICU<\/em> \u2014 impl\u00e9mentation de la biblioth\u00e8que pour travailler avec Unicode de la part d'IBM. <\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"http:\/\/demo.icu-project.org\/icu-bin\/collation.html\">Test de tri avec <em>ICU<\/em> <\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"http:\/\/www.iso.org\/ittf\/ISO14651_2006_TABLE1_en.txt\">Les poids des caract\u00e8res dans <em>ISO 14651<\/em> <\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"http:\/\/www.open-std.org\/JTC1\/SC22\/WG20\/docs\/n972-14652ft.pdf\">Description du format de fichier des poids <em>open-std.org<\/em> <\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/sourceware.org\/bugzilla\/show_bug.cgi?id=14095\">Discussion sur la comparaison des cha\u00eenes dans <em>glibc<\/em><\/a><\/noindex><\/p>\n<p>Source : <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/503960\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0412\u0441\u0451 \u043d\u0430\u0447\u0430\u043b\u043e\u0441\u044c \u0441 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u043b \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u0430\u0434\u0440\u0435\u0441\u0430\u0445 e-mail \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0439 \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0438, \u0441 \u0434\u043e\u043b\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c\u0438 \u0438\u0437 \u0431\u0430\u0437\u044b \u043e\u0442\u0434\u0435\u043b\u0430 \u043a\u0430\u0434\u0440\u043e\u0432. \u041e\u0431\u0430 \u0441\u043f\u0438\u0441\u043a\u0430 \u0431\u044b\u043b\u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0432 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0432 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0435 \u042e\u043d\u0438\u043a\u043e\u0434 UTF-8 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b \u0441 \u044e\u043d\u0438\u043a\u0441\u043e\u0432\u0441\u043a\u0438\u043c\u0438 \u043a\u043e\u043d\u0446\u0430\u043c\u0438 \u0441\u0442\u0440\u043e\u043a. \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 mail.txt \u0418\u0432\u0430\u043d\u043e\u0432 \u0410\u043d\u0434\u0440\u0435\u0439;ia@example.com \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 buhg.txt \u0418\u0432\u0430\u043d\u043e\u0432\u0430 \u0410\u043b\u043b\u0430;\u043c\u0430\u043b\u044f\u0440 \u0401\u043b\u043a\u0438\u043d\u0430 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-83055","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0412\u0441\u0451 \u043d\u0430\u0447\u0430\u043b\u043e\u0441\u044c \u0441 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u043b \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u0430\u0434\u0440\u0435\u0441\u0430\u0445 e-mail \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0439 \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0438, \u0441.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/kak-linuxovskij-sort-sortiruet-stroki\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"fr_FR\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u0430\u043a Linux\u2019\u043e\u0432\u0441\u043a\u0438\u0439 sort \u0441\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0438 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0412\u0441\u0451 \u043d\u0430\u0447\u0430\u043b\u043e\u0441\u044c \u0441 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u043b \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u0430\u0434\u0440\u0435\u0441\u0430\u0445 e-mail \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0439 \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0438, \u0441.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/kak-linuxovskij-sort-sortiruet-stroki\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-05-27T23:42:15+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-05-27T23:42:15+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Comment le sort de Linux trie les cha\u00eenes | ProHoster","description":"Introduction Tout a commenc\u00e9 par un court script qui devait combiner des informations sur les adresses e-mail des employ\u00e9s, obtenues \u00e0 partir d'une liste d'utilisateurs de mailing list, avec.","canonical_url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/kak-linuxovskij-sort-sortiruet-stroki","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"fr_FR","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u0430\u043a Linux\u2019\u043e\u0432\u0441\u043a\u0438\u0439 sort \u0441\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0438 | ProHoster","og:description":"\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0412\u0441\u0451 \u043d\u0430\u0447\u0430\u043b\u043e\u0441\u044c \u0441 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u043b \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u0430\u0434\u0440\u0435\u0441\u0430\u0445 e-mail \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0439 \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0438, \u0441.","og:url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/kak-linuxovskij-sort-sortiruet-stroki","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-05-27T23:42:15+00:00","article:modified_time":"2020-05-27T23:42:15+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"83055","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 15:26:22","updated":"2022-09-27 19:16:08","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/83055","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/comments?post=83055"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/83055\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media?parent=83055"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/categories?post=83055"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/tags?post=83055"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}