{"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\/ro\/blog\/administrirovanie\/kak-linuxovskij-sort-sortiruet-stroki","title":{"rendered":"Cum sorteaz\u0103 Linux sort liniile","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<h1 id=\"vvedenie\">Introducere<\/h1>\n<p><\/p>\n<p>Totul a \u00eenceput cu un script scurt care ar fi trebuit s\u0103 uneasc\u0103 informa\u021biile despre adrese <em>e-mail<\/em> angaja\u021bilor, ob\u021binute din lista de utilizatori ai buletinului informativ, cu func\u021biile angaja\u021bilor, ob\u021binute din baza de date a departamentului de resurse umane. Ambele liste au fost exportate \u00een fi\u0219iere text \u00een codificarea Unicode <em>UTF-8<\/em> \u0219i salvate cu terminatori de linie Unix.<\/p>\n<p><\/p>\n<p>Con\u021binut <em>mail.txt<\/em><\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Ivanov Andrei;ia@example.com<\/code><\/pre>\n<p><\/p>\n<p>Con\u021binut <em>buhg.txt<\/em><\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Ivanova Alla;malear\nYelkina Ella;macara\u0219\nIvanov Andrei;instalator\nAbakanov Mihail;malear<\/code><\/pre>\n<p><\/p>\n<p>Pentru a le uni, fi\u0219ierele au fost sortate cu comanda Unix <em>sort<\/em> \u0219i trimise ca intrare c\u0103tre programul Unix <em>join<\/em>, care s-a \u00eencheiat brusc cu o eroare: <\/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: nu este sortat: Ivanov Andrei;instalator<\/code><\/pre>\n<p><\/p>\n<p>Vizionarea rezultatului sort\u0103rii a ar\u0103tat c\u0103, \u00een general, sortarea este corect\u0103, dar \u00een cazul \u00een care exist\u0103 corespondente \u00eentre numele masculine \u0219i feminine, numele feminine apar \u00eenaintea celor masculine:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; sort buhg.txt\nAbakanov Mihail;malear\nYelkina Ella;macara\u0219\nIvanova Alla;malear\nIvanov Andrei;instalator<\/code><\/pre>\n<p><\/p>\n<p>Pare a fi un bug \u00een sortarea Unicode sau o manifestare a feminismului \u00een algoritmul de sortare. Prima variant\u0103 este, desigur, mai plauzibil\u0103.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>S\u0103 l\u0103s\u0103m deoparte <em>join<\/em> \u0219i s\u0103 ne concentr\u0103m pe <em>sort<\/em>. S\u0103 \u00eencerc\u0103m s\u0103 rezolv\u0103m problema prin \u00eencerc\u0103ri \u0219i erori. Pentru \u00eenceput, s\u0103 schimb\u0103m localitatea de la <em>en_US<\/em> pe <em>ru_RU<\/em>. Pentru sortare ar fi fost suficient s\u0103 set\u0103m variabila de mediu <em>LC_COLLATE<\/em>, dar nu ne vom mul\u021bumi cu pu\u021bin:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; LANG=ru_RU.UTF-8 sort buhg.txt\nAbakanov Mihail;malear\nYelkina Ella;macara\u0219\nIvanova Alla;malear\nIvanov Andrei;instalator<\/code><\/pre>\n<p><\/p>\n<p>Nimic nu s-a schimbat.<\/p>\n<p><\/p>\n<p>S\u0103 \u00eencerc\u0103m s\u0103 recodific\u0103m fi\u0219ierele \u00een codificarea pe un singur byte: <\/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>Din nou, nimic nu s-a schimbat.<\/p>\n<p><\/p>\n<p>Nu avem \u00eencotro, va trebui s\u0103 c\u0103ut\u0103m o solu\u021bie pe internet. Nu exist\u0103 informa\u021bii exact despre numele ruse\u0219ti, dar exist\u0103 \u00eentreb\u0103ri despre alte ciud\u0103\u021benii ale sort\u0103rii. Iat\u0103, de exemplu, o problem\u0103: <noindex><a rel=\"nofollow\" href=\"https:\/\/serverfault.com\/questions\/95579\/unix-sort-treats-dash-characters-as-invisible\/95593\">unix sort trateaz\u0103 caracterele &#8216;-&#8216; (cratim\u0103) ca fiind invizibile<\/a><\/noindex>. \u00cen rezumat, \u0219irurile &quot;a-b&quot;, &quot;aa&quot;, &quot;ac&quot; sunt sortate ca &quot;aa&quot;, &quot;a-b&quot;, &quot;ac&quot;.<\/p>\n<p><\/p>\n<p>R\u0103spunsul este standard peste tot: folose\u0219te localitatea de programare <em>&quot;C&quot;<\/em> \u0219i va fi bine. S\u0103 \u00eencerc\u0103m:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; LANG=C sort buhg.txt\nYelkina Ella;macara\u0219\nAbakanov Mihail;malear\nIvanov Andrei;instalator\nIvanova Alla;avocat<\/code><\/pre>\n<p><\/p>\n<p>S-a schimbat ceva. Ivanovii s-au aranjat \u00een ordinea corect\u0103, dar Iolkina a disp\u0103rut undeva. Revenim la sarcina ini\u021bial\u0103:<\/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>A func\u021bionat f\u0103r\u0103 erori, a\u0219a cum a promis internetul. \u0218i asta \u00een ciuda lui Iolkina \u00een prima linie.<\/p>\n<p><\/p>\n<p>Problema pare s\u0103 fie rezolvat\u0103, dar pentru orice eventualitate vom \u00eencerca \u00eenc\u0103 o codare rus\u0103 - cea 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=ro_RO.CP1251 sort \n | iconv -f CP1251 -t UTF8 <\/code><\/pre>\n<p><\/p>\n<p>Rezultatul sort\u0103rii, ciudat, va coincide cu localele <em>&quot;C&quot;<\/em>, \u0219i \u00eentreaga demonstra\u021bie, \u00een consecin\u021b\u0103, trece f\u0103r\u0103 erori. E o adev\u0103rat\u0103 minune.<\/p>\n<p><\/p>\n<p>Nu-mi place minunile \u00een programare, deoarece, de obicei, ele mascheaz\u0103 erorile. Va trebui s\u0103 m\u0103 ocup serios de \u00eentrebarea cum func\u021bioneaz\u0103 <em>sort<\/em> \u0219i la ce influen\u021beaz\u0103 <em>LC_COLLATE<\/em> .<\/p>\n<p><\/p>\n<p>\u00cen final, voi \u00eencerca s\u0103 r\u0103spund la \u00eentreb\u0103rile:<\/p>\n<p><\/p>\n<ul>\n<li>de ce nu erau sortate corect numele de femei<\/li>\n<li>de ce <em>LANG=ro_RO.CP1251<\/em> s-a dovedit a fi echivalent <em>LANG=C<\/em><\/li>\n<li>de ce au <em>sort<\/em> \u0219i <em>join<\/em> reprezent\u0103ri diferite despre ordinea liniilor sortate<\/li>\n<li>de ce \u00een toate exemplele mele sunt erori<\/li>\n<li>\u00een fine, cum s\u0103 sortezi liniile dup\u0103 bunul t\u0103u plac<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"sortirovka-v-yunikode\">Sortarea \u00een Unicode<\/h1>\n<p><\/p>\n<p>Prima oprire va fi raportul tehnic nr. 10 intitulat <noindex><a rel=\"nofollow\" href=\"https:\/\/unicode.org\/reports\/tr10\/\">algoritmul de collation Unicode<\/a><\/noindex> site-ul nostru <noindex><a rel=\"nofollow\" href=\"https:\/\/unicode.org\">unicode.org<\/a><\/noindex>. Raportul con\u021bine multe detalii tehnice, a\u0219a c\u0103 \u00eemi permit s\u0103 ofer un rezumat al ideilor principale.<\/p>\n<p><\/p>\n<p><em>Collation<\/em> \u2014 &quot;compararea&quot; \u0219irurilor este baza fiec\u0103rui algoritm de sortare. Algoritmii pot diferi (&quot;bule&quot;, &quot;\u00eembinare&quot;, &quot;rapid&quot;), dar to\u021bi vor utiliza compararea a dou\u0103 \u0219iruri pentru a determina ordinea acestora.<\/p>\n<p><\/p>\n<p>Sortarea liniilor \u00een limbile naturale este o problem\u0103 destul de complex\u0103. Chiar \u0219i \u00een cele mai simple codific\u0103ri pe un byte, ordinea literelor din alfabet, orice ar fi diferit de alfabetul englez, nu va coincide cu ordinea valorilor numerice cu care sunt codificate aceste litere. Astfel, \u00een alfabetul german, litera <em>\u00d6<\/em> se afl\u0103 \u00eentre <em>O<\/em> \u0219i <em>P<\/em>, iar \u00een codarea <em>CP850<\/em> se afl\u0103 \u00eentre <em>\u00ff<\/em> \u0219i <em>\u00dc<\/em>.<\/p>\n<p><\/p>\n<p>Se poate \u00eencerca abstractizarea de la o codificare specific\u0103 \u0219i a considera &quot;literele ideale&quot; care sunt a\u0219ezate \u00eentr-o anumit\u0103 ordine, a\u0219a cum este realizat \u00een Unicode. Codific\u0103rile <em>UTF8<\/em>, <em>UTF16<\/em> sau un byte <em>KOI8-R<\/em> (dac\u0103 este necesar un subset limitat de Unicode) vor oferi reprezent\u0103ri numerice diferite ale literelor, dar se vor referi la acelea\u0219i elemente din tabela de baz\u0103. <\/p>\n<p><\/p>\n<p>Se pare c\u0103 chiar \u0219i construind o tabel\u0103 de caractere de la zero, nu vom putea stabili un ordonare universal\u0103 a caracterelor. \u00cen diferite alfabeturi na\u021bionale care folosesc acelea\u0219i litere, ordinea acestor litere poate diferi. De exemplu, \u00een limba francez\u0103 <em>\u00c6<\/em> va fi considerat\u0103 o ligatur\u0103 \u0219i sortat\u0103 ca un \u0219ir <em>AE<\/em>. \u00cen limba norvegian\u0103 <em>\u00c6<\/em> va fi o liter\u0103 separat\u0103, care se plaseaz\u0103 dup\u0103 <em>Z<\/em>. Apropo, pe l\u00e2ng\u0103 ligaturi de tipul <em>\u00c6<\/em> exist\u0103 litere care sunt scrise cu mai multe caractere. De exemplu, \u00een alfabetul ceh exist\u0103 litera <em>Ch<\/em>, care se afl\u0103 \u00eentre <em>H<\/em> \u0219i <em>I<\/em>.<\/p>\n<p><\/p>\n<p>. Pe l\u00e2ng\u0103 diferen\u021bele dintre alfabete, exist\u0103 \u0219i alte tradi\u021bii na\u021bionale care influen\u021beaz\u0103 ordonarea. \u00cen special, apare \u00eentrebarea: \u00een ce ordine ar trebui s\u0103 urmeze \u00een dic\u021bionar cuvintele formate din litere mari \u0219i litere mici? De asemenea, ordonarea poate fi influen\u021bat\u0103 de particularit\u0103\u021bile utiliz\u0103rii semnelor de punctua\u021bie. \u00cen limba spaniol\u0103, la \u00eenceputul unei propozi\u021bii interogative se pune semnul \u00eentreb\u0103rii \u00eentors (<em>\u00bfTe gusta la m\u00fasica?<\/em>). \u00cen acest caz, este evident c\u0103 propozi\u021biile interogative nu ar trebui s\u0103 fie grupate \u00eentr-un cluster separat din afara alfabetului, iar cum s\u0103 sort\u0103m \u0219irurile cu alte semne de punctua\u021bie?<\/p>\n<p><\/p>\n<p>Nu voi insista asupra ordon\u0103rii \u0219irurilor \u00een limbi care difer\u0103 semnificativ de limbile europene. Voi sublinia c\u0103 \u00een limbile cu direc\u021bia de scriere de la dreapta la st\u00e2nga sau de sus \u00een jos, caracterele din \u0219iruri sunt, cel mai probabil, stocate \u00een ordinea lecturii, iar chiar \u0219i \u00een scrierile non-alfabetice exist\u0103 propriile metode de ordonare pe caractere. De exemplu, hieroglifurile pot fi ordonate dup\u0103 form\u0103 (<noindex><a rel=\"nofollow\" href=\"https:\/\/studychinese.ru\/kljuchi\/\">cheile hieroglifelor chineze\u0219ti<\/a><\/noindex>) sau dup\u0103 pronun\u021bie. Cum ar trebui ordonate emoji-urile, sincer s\u0103 fiu, nu \u00eemi dau seama, dar pentru ele se poate inventa ceva.<\/p>\n<p><\/p>\n<p>Pe baza caracteristicilor enumerate mai sus, au fost formulate cerin\u021bele de baz\u0103 pentru compararea \u0219irurilor, bazate pe tabele Unicode:<\/p>\n<p><\/p>\n<ul>\n<li>compararea \u0219irurilor nu depinde de pozi\u021bia caracterelor \u00een tabela de coduri;<\/li>\n<li>secven\u021bele de caractere care formeaz\u0103 un singur caracter sunt aduse la forma canonic\u0103 (<em>A<\/em> + cercule\u021bul de sus este acela\u0219i cu <em>\u00c5<\/em>);<\/li>\n<li>\u00een compararea \u0219irurilor, caracterul este considerat \u00een contextul \u0219irului \u0219i, dac\u0103 este necesar, este combinat cu vecinii \u00eentr-o singur\u0103 unitate de compara\u021bie (<em>Ch<\/em> \u00een ceh\u0103) sau este \u00eemp\u0103r\u021bit \u00een mai multe (<em>\u00c6<\/em> \u00een francez\u0103);<\/li>\n<li>toate caracteristicile na\u021bionale (alfabet, litere mari\/mici, semne de punctua\u021bie, ordinea tipurilor de scriere) trebuie s\u0103 fie configurate p\u00e2n\u0103 la o asignare manual\u0103 a ordinii (emoji);<\/li>\n<li>compara\u021bia este important\u0103 nu doar pentru sortare, ci \u0219i \u00een multe alte locuri, de exemplu pentru a defini intervalele de r\u00e2nduri (substituirea {A\u2026 \u044f} \u00een <em>bash<\/em>);<\/li>\n<li>compara\u021bia trebuie s\u0103 se realizeze suficient de repede.<\/li>\n<\/ul>\n<p><\/p>\n<p>\u00cen plus, autorii raportului au formulat propriet\u0103\u021bi ale compara\u021biei pe care dezvoltatorii de algoritmi nu ar trebui s\u0103 se bazeze:<\/p>\n<p><\/p>\n<ul>\n<li>algoritmul de compara\u021bie nu ar trebui s\u0103 necesite un set separat de caractere pentru fiecare limb\u0103 (limbile rus\u0103 \u0219i ucrainean\u0103 folosesc \u00eempreun\u0103 majoritatea caracterelor chirilice);<\/li>\n<li>compara\u021bia nu ar trebui s\u0103 se bazeze pe ordinea caracterelor din tabelele Unicode;<\/li>\n<li>greutatea unui \u0219ir nu ar trebui s\u0103 fie un atribut al \u0219irului, deoarece acela\u0219i \u0219ir \u00een diferite contexte culturale poate avea greut\u0103\u021bi diferite;<\/li>\n<li>greut\u0103\u021bile \u0219irurilor pot varia la fuziune sau la divizare (din <em>x<\/em> &lt; <em>Stabili\u021bi o parol\u0103 \u0219i p\u0103stra\u021bi-o \u00een siguran\u021b\u0103!<\/em> nu \u00eenseamn\u0103 c\u0103 <em>xz<\/em> &lt; <em>yz<\/em>);<\/li>\n<li>\u0219iruri diferite, care au aceea\u0219i greutate, sunt considerate egale din perspectiva algoritmului de sortare. Introducerea unui ordin suplimentar pentru astfel de \u0219iruri este posibil\u0103, dar poate reduce performan\u021ba;<\/li>\n<li>la sort\u0103rile repetate, \u0219irurile cu aceea\u0219i greutate se pot schimba \u00eentre ele. Stabilitatea este o proprietate specific\u0103 a unui algoritm de sortare, nu a algoritmului de compara\u021bie a \u0219irurilor (vezi punctul anterior);<\/li>\n<li>regulile de sortare se pot schimba \u00een timp pe m\u0103sur\u0103 ce tradi\u021biile culturale sunt clarificate\/alterate.<\/li>\n<\/ul>\n<p><\/p>\n<p>De asemenea, se stipuleaz\u0103 c\u0103 algoritmul de compara\u021bie nu are cuno\u0219tin\u021be despre semantica \u0219irurilor procesate. Astfel, \u0219irurile formate doar din cifre nu ar trebui s\u0103 fie comparate ca numere, iar \u00een listele de denumiri \u00een englez\u0103, articolul nu ar trebui omis (<em>Beatles, The<\/em>).<\/p>\n<p><\/p>\n<p>Pentru a satisface toate cerin\u021bele men\u021bionate, a fost propus un algoritm de sortare \u00een mai multe niveluri (de fapt, patru niveluri).<\/p>\n<p><\/p>\n<p>\u00cen prealabil, caracterele din \u0219ir sunt aduse la forma canonic\u0103 \u0219i grupate \u00een unit\u0103\u021bi de compara\u021bie. Fiec\u0103rei unit\u0103\u021bi de compara\u021bie i se atribuie mai multe greut\u0103\u021bi, corespunz\u0103toare mai multor niveluri de compara\u021bie. Greut\u0103\u021bile unit\u0103\u021bilor de compara\u021bie sunt elemente ale mul\u021bimilor ordonate (\u00een acest caz numere \u00eentregi), care pot fi comparate ca fiind mai mari sau mai mici. Valoarea special\u0103 <em>IGNORED<\/em> (0x0) \u00eenseamn\u0103 c\u0103 la nivelul corespunz\u0103tor compara\u021biei, aceast\u0103 unitate nu particip\u0103 la compara\u021bie. Compara\u021bia stringurilor poate fi repetat\u0103 de mai multe ori, folosind greut\u0103\u021bi corespunz\u0103toare nivelurilor. La fiecare nivel, greut\u0103\u021bile unit\u0103\u021bilor de compara\u021bie ale celor dou\u0103 stringuri sunt comparate una cu cealalt\u0103.<\/p>\n<p><\/p>\n<p>\u00cen diferite implement\u0103ri ale algoritmului pentru tradi\u021bii na\u021bionale diferite, valorile coeficientului pot varia, dar standardul Unicode include o tabel\u0103 de greut\u0103\u021bi de baz\u0103 \u2014 <em>&quot;Default Unicode Collation Element Table&quot;<\/em> (<em>DUCET<\/em>). Vreau s\u0103 men\u021bionez c\u0103 setarea variabilei <em>LC_COLLATE<\/em> constituie de fapt o indica\u021bie pentru alegerea tabelei de greut\u0103\u021bi \u00een func\u021bia de compara\u021bie a stringurilor.<\/p>\n<p><\/p>\n<p>Coeficientii de greutate <em>DUCET<\/em> sunt structura\u021bi astfel:<\/p>\n<p><\/p>\n<ul>\n<li>la primul nivel, toate literele sunt aduse la acela\u0219i registru, semnele diacritice sunt eliminate, iar semnele de punctua\u021bie (nu toate) sunt ignorate;<\/li>\n<li>la al doilea nivel, se iau \u00een considerare numai semnele diacritice;<\/li>\n<li>la al treilea nivel, se ia \u00een considerare numai registrul;<\/li>\n<li>la al patrulea nivel, se iau \u00een considerare doar semnele de punctua\u021bie.<\/li>\n<\/ul>\n<p><\/p>\n<p>Compara\u021bia se desf\u0103\u0219oar\u0103 \u00een mai multe treceri: mai \u00eent\u00e2i se compar\u0103 coeficientii de la primul nivel; dac\u0103 greut\u0103\u021bile coincid, se face o compara\u021bie repetat\u0103 cu greut\u0103\u021bile celui de-al doilea nivel; apoi, posibil, al treilea \u0219i al patrulea.<\/p>\n<p><\/p>\n<p>Compara\u021bia se \u00eencheie atunci c\u00e2nd \u00een stringuri se g\u0103sesc unit\u0103\u021bi de compara\u021bie corespunz\u0103toare cu greut\u0103\u021bi diferite. Stringurile care au greut\u0103\u021bi egale la toate cele patru niveluri sunt considerate egale \u00eentre ele.<\/p>\n<p><\/p>\n<p>Acest algoritm (cu o mul\u021bime de detalii tehnice suplimentare) a dat denumirea raportului nr. 10 \u2014 <em>&quot;Unicode Collation Algorithm&quot;<\/em> (<em>UCA<\/em>).<\/p>\n<p><\/p>\n<p>\u00cen acest loc, comportamentul sort\u0103rii din exemplul nostru devine pu\u021bin mai clar. Ar fi bine s\u0103-l compar\u0103m cu standardul Unicode.<\/p>\n<p><\/p>\n<p>Pentru testarea implement\u0103rilor <em>UCA<\/em> exist\u0103 un <noindex><a rel=\"nofollow\" href=\"https:\/\/www.unicode.org\/Public\/UCA\/latest\/CollationTest.html\">test<\/a><\/noindex>, care utilizeaz\u0103 <noindex><a rel=\"nofollow\" href=\"http:\/\/www.unicode.org\/Public\/UCA\/latest\/allkeys.txt\">fi\u0219ierul de greut\u0103\u021bi<\/a><\/noindex>, implement\u00e2nd <em>DUCET<\/em>. \u00cen fi\u0219ierul de greut\u0103\u021bi pot fi g\u0103site diverse curiozit\u0103\u021bi. De exemplu, exist\u0103 ordinea pieselor de mahjong \u0219i a domino-ului european, precum \u0219i ordinea simbolurilor \u00een pachetul de c\u0103r\u021bi (simbolul <em>1F000<\/em> \u0219i a\u0219a mai departe). Mastrele c\u0103r\u021bilor sunt aranjate conform regulilor de bridge \u2014 PCHBT, iar c\u0103r\u021bile dintr-o suit\u0103 \u2014 \u00een ordinea T,2,3\u2026 K.<\/p>\n<p><\/p>\n<p>Verificarea manual\u0103 a corectitudinii sort\u0103rii stringurilor conform <em>DUCET<\/em> ar fi fost destul de obositoare, dar, din fericire pentru noi, exist\u0103 o implementare exemplar\u0103 a unei biblioteci pentru lucrul cu Unicode \u2014 &quot;<noindex><a rel=\"nofollow\" href=\"http:\/\/site.icu-project.org\/\">Componente Interna\u021bionale pentru Unicode<\/a><\/noindex>&quot; (<em>ICU<\/em>).<\/p>\n<p><\/p>\n<p>Pe site-ul acestei biblioteci, dezvoltat\u0103 \u00een <em>IBM<\/em>, exist\u0103 pagini de demonstra\u021bie, inclusiv <noindex><a rel=\"nofollow\" href=\"http:\/\/demo.icu-project.org\/icu-bin\/collation.html\">pagina algoritmului de comparare a stringurilor<\/a><\/noindex>. Introducem stringurile noastre de testare cu set\u0103rile implicite \u0219i, oh, minune, ob\u021binem o sortare perfect\u0103 \u00een rus\u0103.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Abakanov Mihail; zugrav\nElkina Ella; macaragiu\nIvanov Andrei; instalator\nIvanova Alla; avocat<\/code><\/pre>\n<p><\/p>\n<p>Apropo, pe site-ul <em>ICU<\/em> po\u021bi g\u0103si clarific\u0103ri despre modul de func\u021bionare al algoritmului de comparare \u00een cazul proces\u0103rii semnelor de punctua\u021bie. \u00cen exemplele <noindex><a rel=\"nofollow\" href=\"http:\/\/userguide.icu-project.org\/collation\/faq\">\u00centreb\u0103ri frecvente despre Collation<\/a><\/noindex> se ignor\u0103 apostroful \u0219i cratima.<\/p>\n<p><\/p>\n<p>Unicode ne-a ajutat, dar va trebui s\u0103 c\u0103ut\u0103m motivele comportamentului ciudat <em>sort<\/em> \u00een <em>Linux<\/em> \u00een alt\u0103 parte.<\/p>\n<p><\/p>\n<h1 id=\"sortirovka-v-glibc\">Sortare \u00een glibc<\/h1>\n<p><\/p>\n<p>O privire rapid\u0103 asupra codului surs\u0103 al utilitarului <em>sort<\/em> din <em>GNU Core Utils<\/em> a ar\u0103tat c\u0103 localizarea \u00een utilitar se reduce la afi\u0219area valorii curente a variabilei <em>LC_COLLATE<\/em> la pornirea \u00een modul de depanare:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$ sort --debug buhg.txt &gt; buhg.srt\nsort: folosind regulile de sortare 'en_US.UTF8'<\/code><\/pre>\n<p><\/p>\n<p>Compararea stringurilor se face cu func\u021bia standard <em>strcoll<\/em>, ceea ce \u00eenseamn\u0103 c\u0103 tot ce este interesant se afl\u0103 \u00een biblioteca <em>glibc<\/em>.<\/p>\n<p><\/p>\n<p>Pe <em>wiki<\/em> proiectului <em>glibc<\/em> care este consacrat\u0103 compar\u0103rii stringurilor <noindex><a rel=\"nofollow\" href=\"https:\/\/sourceware.org\/glibc\/wiki\/Locales#LC_COLLATE\">unui paragraf<\/a><\/noindex>. Din acest paragraf putem \u00een\u021belege c\u0103 \u00een <em>glibc<\/em> sortarea se bazeaz\u0103 pe algoritmul deja cunoscut <em>UCA<\/em> (<em>Algoritmul de collation Unicode<\/em>) \u0219i\/sau pe un standard apropiat <em>ISO 14651<\/em> (<em>Ordinea \u0219i compararea stringurilor interna\u021bionale<\/em>). Despre acest ultim standard trebuie remarcat faptul c\u0103 pe site-ul <noindex><a rel=\"nofollow\" href=\"https:\/\/standards.iso.org\/ittf\/PubliclyAvailableStandards\">standards.iso.org<\/a><\/noindex> <em>ISO 14651<\/em> este declarat oficial accesibil publicului, dar linkul corespunz\u0103tor duce la o pagin\u0103 inexistent\u0103. Google ofer\u0103 c\u00e2teva pagini cu linkuri c\u0103tre site-uri oficiale care ofer\u0103 cump\u0103rarea unei copii electronice a standardului pentru o sut\u0103 de euro, dar pe a treia sau a patra pagin\u0103 din rezultatele c\u0103ut\u0103rii se pot g\u0103si \u0219i linkuri directe c\u0103tre <em>PDF<\/em>. \u00cen general, standardul nu se deosebe\u0219te foarte mult de <em>UCA<\/em>, dar este mai pu\u021bin captivant, deoarece nu con\u021bine exemple vii ale particularit\u0103\u021bilor na\u021bionale ale sort\u0103rii stringurilor. <\/p>\n<p><\/p>\n<p>Cea mai interesant\u0103 informa\u021bie de pe <em>wiki<\/em> s-a dovedit a fi un link c\u0103tre <noindex><a rel=\"nofollow\" href=\"https:\/\/sourceware.org\/bugzilla\/show_bug.cgi?id=14095\">bug tracker<\/a><\/noindex> cu discu\u021bii despre implementarea compar\u0103rii stringurilor \u00een <em>glibc<\/em>. Din discu\u021bie putem \u00eenv\u0103\u021ba c\u0103 \u00een <em>glibc<\/em> pentru compararea stringurilor se folose\u0219te <em>ISO<\/em>tabelul <noindex><a rel=\"nofollow\" href=\"http:\/\/www.iso.org\/ittf\/ISO14651_2006_TABLE1_en.txt\">Tabela Comun\u0103 de \u0218abloane<\/a><\/noindex> (<em>CTT<\/em>), adresa c\u0103ruia poate fi g\u0103sit\u0103 \u00een anexa <em>A<\/em> standardului <em>ISO 14651<\/em>. \u00centre anii 2000 \u0219i 2015, acest tabel \u00een <em>glibc<\/em> nu avea un men\u021bin\u0103tor \u0219i se deosebea destul de mult (cel pu\u021bin exterior) de versiunea actual\u0103 a standardului. \u00centre 2015 \u0219i 2018 a avut loc adaptarea la noua versiune a tabelului \u0219i \u00een prezent ave\u021bi \u0219ansa s\u0103 \u00eent\u00e2lni\u021bi \u00een via\u021ba real\u0103 at\u00e2t varianta nou\u0103 a tabelului (<em>CentOS 8<\/em>), c\u00e2t \u0219i cea veche (<em>CentOS 7<\/em>). <\/p>\n<p><\/p>\n<p>Acum, c\u00e2nd avem toat\u0103 informa\u021bia despre algoritm \u0219i tabelele auxiliare, putem reveni la problema ini\u021bial\u0103 \u0219i \u00een\u021belege cum s\u0103 sort\u0103m corect \u0219irurile \u00een localizarea rus\u0103.<\/p>\n<p><\/p>\n<h1 id=\"iso-1465114652\">ISO 14651\/14652<\/h1>\n<p><\/p>\n<p>Codul surs\u0103 al tabelului care ne intereseaz\u0103 <em>CTT<\/em> \u00een majoritatea distribu\u021biilor <em>Linux<\/em> se afl\u0103 \u00een directorul <em>\/usr\/share\/i18n\/locales\/<\/em>. Tabelul \u00eensu\u0219i se afl\u0103 \u00een fi\u0219ierul <em>iso14651_t1_common<\/em>. Apoi, acest fi\u0219ier cu directiva <em>copy iso14651_t1_common<\/em> este inclus \u00een fi\u0219ierul <em>iso14651_t1<\/em>, care, la r\u00e2ndul s\u0103u, este inclus \u00een fi\u0219ierele na\u021bionale, inclusiv \u00een <em>en_US<\/em> \u0219i <em>ru_RU<\/em>. \u00cen majoritatea distribu\u021biilor <em>Linux<\/em> toate fi\u0219ierele surs\u0103 sunt incluse \u00een instala\u021bia de baz\u0103, dar dac\u0103 nu sunt disponibile, va trebui s\u0103 instala\u021bi un pachet suplimentar din distribu\u021bie.<\/p>\n<p><\/p>\n<p>Structura fi\u0219ierului <em>iso14651_t1<\/em> poate p\u0103rea extrem de detaliat\u0103, cu reguli de denumire neclare, dar dac\u0103 analiza\u021bi, totul este destul de simplu. Structura este descris\u0103 \u00een standardul <em>ISO 14652<\/em>, o copie a c\u0103ruia poate fi desc\u0103rcat\u0103 de pe site-ul <noindex><a rel=\"nofollow\" href=\"http:\/\/www.open-std.org\/JTC1\/SC22\/WG20\/docs\/n972-14652ft.pdf\">open-std.org<\/a><\/noindex>. O alt\u0103 descriere a formatului fi\u0219ierului poate fi citit\u0103 \u00een <noindex><a rel=\"nofollow\" href=\"https:\/\/pubs.opengroup.org\/onlinepubs\/9699919799\/basedefs\/V1_chap07.html\">specifica\u021bii<\/a><\/noindex> <em>POSIX<\/em> de la <em>OpenGroup<\/em>. Ca alternativ\u0103 la citirea standardului, pute\u021bi studia codul surs\u0103 al func\u021biei <em>collate_read<\/em> \u00een <em>glibc\/locale\/programs\/ld-collate.c<\/em>.<\/p>\n<p><\/p>\n<p>Structura fi\u0219ierului arat\u0103 astfel:<\/p>\n<p><\/p>\n<p>\u00cen mod implicit, simbolul este folosit ca simbol de escape, iar sf\u00e2r\u0219itul liniei dup\u0103 simbolul # este un comentariu. Ambele simboluri pot fi redefine, ceea ce a fost realizat \u00een noua versiune a tabelului:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">escape_char \/\ncomment_char %<\/code><\/pre>\n<p><\/p>\n<p>\u00cen fi\u0219ier vor ap\u0103rea tokeni \u00een formatul <em>&lt;Uxxxx&gt;<\/em> sau <em>&lt;Uxxxxxxxx&gt;<\/em> (unde <em>x<\/em> \u2014 este o cifr\u0103 hexadecimal\u0103). Aceasta reprezint\u0103 reprezentarea hexadecimal\u0103 a pozi\u021biilor de cod Unicode \u00een codificarea <em>UCS-4<\/em> (<em>UTF-32<\/em>). Toate celelalte elemente din paranteze unghiulare (inclusiv <em>&lt;Uxxxx_xxxx&gt;<\/em>, <em>&lt;2&gt;<\/em> \u0219i similare), sunt considerate constante de \u0219iruri simple, f\u0103r\u0103 un sens special \u00een afara contextului.<\/p>\n<p><\/p>\n<p>\u0218irul <em>LC_COLLATE<\/em> ne spune c\u0103 datele care urmeaz\u0103 descriu compara\u021bia \u0219irurilor.<\/p>\n<p><\/p>\n<p>Mai \u00eent\u00e2i se stabilesc numele pentru greut\u0103\u021bi \u00een tabelul de compara\u021bie \u0219i numele pentru combina\u021biile de simboluri. \u00cen general, cele dou\u0103 tipuri de nume apar\u021bin unor entit\u0103\u021bi diferite, dar \u00een fi\u0219ierul real sunt amestecate. Numele greut\u0103\u021bilor sunt definite prin cuv\u00e2ntul cheie <em>collating-symbol<\/em> (simbol de comparare), deoarece atunci c\u00e2nd se compar\u0103 simbolurile Unicode cu greut\u0103\u021bi identice, acestea vor fi considerate simboluri echivalente.<\/p>\n<p><\/p>\n<p>Lungimea total\u0103 a sec\u021biunii \u00een revizia curent\u0103 a fi\u0219ierului este de aproximativ 900 de linii. Am extras exemple din mai multe locuri pentru a ilustra arbitraritatea numelui \u0219i c\u00e2teva tipuri de sintax\u0103.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">LC_COLLATE\n\nsimbol-de-sortare &lt;RES-1&gt;\nsimbol-de-sortare &lt;BLK&gt;\nsimbol-de-sortare &lt;MIN&gt;\nsimbol-de-sortare &lt;WIDE&gt;\n...\nsimbol-de-sortare &lt;ARABIC&gt;\nsimbol-de-sortare &lt;ETHPC&gt;\nsimbol-de-sortare &lt;OSMANYA&gt;\n...\nsimbol-de-sortare &lt;S1D000&gt;..&lt;S1D35F&gt;\nsimbol-de-sortare &lt;SFFFF&gt; % Valoarea simbolului cea mai mare garantat\u0103. P\u0103streaz\u0103 la finalul acestei liste\n...\nelement-de-sortare &lt;U0413_0301&gt; din &quot;&lt;U0413&gt;&lt;U0301&gt;&quot;\nelement-de-sortare &lt;U0413_0341&gt; din &quot;&lt;U0413&gt;&lt;U0341&gt;&quot;<\/code><\/pre>\n<p><\/p>\n<ul>\n<li><em>collating-symbol<\/em> \u00eenregistreaz\u0103 un \u0219ir <em>OSMANYA<\/em> \u00een tabelul de nume ale greut\u0103\u021bilor <\/li>\n<li><em>collating-symbol ..<\/em> \u00eenregistreaz\u0103 o secven\u021b\u0103 de nume format\u0103 dintr-un prefix <em>S<\/em> \u0219i un sufix numeric hexazecimal din <em>1D000<\/em> la <em>1D35F<\/em>.<\/li>\n<li><em>FFFF<\/em> \u00een <em>collating-symbol<\/em> arat\u0103 ca un \u00eentreg nesemnat mare \u00een sistemul de numerotare hexazecimal\u0103, dar <em>&lt;SFFFF&gt;<\/em> este doar un nume care ar putea ar\u0103ta ca <em>&lt;VERYBIGVAL&gt;<\/em> <\/li>\n<li>nume <em>&lt;U0413&gt;<\/em> reprezint\u0103 un punct de cod \u00een codificare <em>UCS-4<\/em><\/li>\n<li><em>element-de-sortare &lt;U0413_0301&gt; din &quot;&lt;U0413&gt;&lt;U0301&gt;&quot;<\/em> \u00eenregistreaz\u0103 un nou nume pentru o pereche de puncte Unicode. <\/li>\n<\/ul>\n<p><\/p>\n<p>C\u00e2nd numele greut\u0103\u021bilor sunt definite, sunt stabilite greut\u0103\u021bile propriu-zise. Deoarece \u00een compara\u021bie conteaz\u0103 doar rela\u021biile mai-mult-mai-pu\u021bin, greut\u0103\u021bile sunt definite printr-o simpl\u0103 secven\u021b\u0103 de enumerare a numelui. Mai \u00eent\u00e2i sunt enumerate greut\u0103\u021bile &quot;mai u\u0219oare&quot;, apoi cele &quot;mai grele&quot;. Iat\u0103, fiec\u0103rui simbol Unicode i se aloc\u0103 patru greut\u0103\u021bi diferite. Aici sunt consolidate \u00eentr-o secven\u021b\u0103 ordonat\u0103 unic\u0103. Teoretic, orice nume simbolic poate fi utilizat pe oricare dintre cele patru niveluri, dar comentariile sugereaz\u0103 c\u0103 dezvoltatorii \u00ee\u0219i \u00eempart mental numele pe niveluri.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">% Aloc\u0103rile de greutate simbolic\u0103\n\n% Aloc\u0103rile de greutate de nivelul 3\n\n\n\n\n...\n% Aloc\u0103rile de greutate de nivelul 2\n\n % LINIE DE COMBINARE JOAS\u0102\n % VIRGUL\u0102 DEASUPRA\n % VIRGUL\u0102 \u00ceNREVERZAT\u0102 DEASUPRA\n...\n% Aloc\u0103rile de greutate de nivelul 1\n % TABULARE ORIZONTAL\u0102\n % \u00ceNCHEIERE LINIE\n % TABULARE VERTICAL\u0102\n...\n % LITERA MIC\u0102 CYRILIC\u0102 DE\n % LITERA MIC\u0102 CYRILIC\u0102 KOMI DE\n % LITERA MIC\u0102 CYRILIC\u0102 DJE\n % LITERA MIC\u0102 CYRILIC\u0102 KOMI DJE\n % LITERA MIC\u0102 CYRILIC\u0102 GJE\n % LITERA MIC\u0102 CYRILIC\u0102 ZE CU DESCENS\n % LITERA MIC\u0102 CYRILIC\u0102 IE\n % LITERA MIC\u0102 CYRILIC\u0102 IE CU BREVE\n % LITERA MIC\u0102 CYRILIC\u0102 IE UCRAINEAN\u0102\n % LITERA MIC\u0102 CYRILIC\u0102 ZHE<\/code><\/pre>\n<p><\/p>\n<p>\u00cen cele din urm\u0103, tabelul greut\u0103\u021bilor propriu-zis.<\/p>\n<p><\/p>\n<p>Sec\u021biunea greut\u0103\u021bilor este \u00eenchis\u0103 \u00een r\u00e2nduri cu cuvinte cheie <em>order_start<\/em> \u0219i <em>order_end<\/em>. Parametrii suplimentari <em>order_start<\/em> stabile\u0219te \u00een ce direc\u021bie sunt examinate r\u00e2ndurile la fiecare nivel de compara\u021bie. Prin default, se folose\u0219te parametrul <em>forward<\/em>. Corpul sec\u021biunii const\u0103 din r\u00e2nduri care con\u021bin codul simbolului \u0219i cele patru greut\u0103\u021bi ale acestuia. Codul simbolului poate fi reprezentat de simbolul \u00eensu\u0219i, de punctul de cod sau de numele simbolic definit anterior. Greut\u0103\u021bile pot fi, de asemenea, specificate prin nume simbolice, puncte de cod sau simboluri \u00een sine. Dac\u0103 se folosesc puncte de cod sau simboluri, atunci greutatea lor coincide cu valoarea numeric\u0103 a punctului de cod (pozi\u021bia \u00een tabelul Unicode). Simbolurile care nu sunt specificate explicit (a\u0219a cum \u00eemi d\u0103 impresia) sunt considerate a fi atribuite \u00een tabel cu o greutate primar\u0103, care coincide cu pozi\u021bia \u00een tabelul Unicode. Valoarea special\u0103 a greut\u0103\u021bii <em>IGNORE<\/em> semnific\u0103 faptul c\u0103 la nivelul respectiv de compara\u021bie, acest simbol este ignorat.<\/p>\n<p><\/p>\n<p>Pentru a demonstra structura greut\u0103\u021bilor, am ales trei fragmente destul de evidente:<\/p>\n<p><\/p>\n<ul>\n<li>simboluri care sunt complet ignorate<\/li>\n<li>simboluri echivalente cu cifra trei la primele dou\u0103 niveluri<\/li>\n<li>\u00eenceputul alfabetului chirilic, care nu con\u021bine semne diacritice \u0219i, prin urmare, este sortat \u00een principal pe baza primului \u0219i al treilea nivel.<\/li>\n<\/ul>\n<p><\/p>\n<pre><code class=\"plaintext\">ordine_start forward;forward;forward;forward,pozitie\n IGNORE;IGNORE;IGNORE;IGNORE % NULL (in 6429)\n IGNORE;IGNORE;IGNORE;IGNORE % \u00ceNCEPUTUL ANTETULUI (in 6429)\n IGNORE;IGNORE;IGNORE;IGNORE % \u00ceNCEPUTUL TEXTULUI (in 6429)\n...\n ;;; % CIFRA TREI\n ;;; % CIFRA TREI \u00ceN PLIN\n ;;; % CIFRA TREI \u00ceN PARANTEZE\n ;;; % CIFRA TREI PUNCT\n ;;<FONT>; % CIFRA TREI BOLD MATEMATIC\n...\n ;;; % LITERA MIC\u0102 CYRILIC\u0102 A\n ;;; % LITERA MARE CYRILIC\u0102 A\n ;;; % LITERA MIC\u0102 CYRILIC\u0102 A CU BREVI\n ;;; % LITERA MIC\u0102 CYRILIC\u0102 A CU BREVI\n...\n ;;; % LITERA MIC\u0102 CYRILIC\u0102 BE\n ;;; % LITERA MARE CYRILIC\u0102 BE\n ;;; % LITERA MIC\u0102 CYRILIC\u0102 VE\n ;;; % LITERA MARE CYRILIC\u0102 VE\n...\nordine_end<\/code><\/pre>\n<p><\/p>\n<p>Acum putem reveni la sortarea exemplelor din \u00eenceputul articolului. Problema este \u00een aceast\u0103 parte a tabelului greut\u0103\u021bilor:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">IGNORE;IGNORE;IGNORE; % SPA\u021aIU\n IGNORE;IGNORE;IGNORE; % SEMN DE EXCLAMARE\n IGNORE;IGNORE;IGNORE; % SEMN DE \u00ceNTREBARE\n...<\/code><\/pre>\n<p><\/p>\n<p>Se observ\u0103 c\u0103 \u00een acest tabel semnele de punctua\u021bie din tabelul <em>ASCII<\/em> (inclusiv spa\u021biul) sunt practic \u00eentotdeauna ignorate la compararea \u0219irurilor. Excep\u021bia o constituie doar \u0219irurile care coincid \u00een totalitate, cu excep\u021bia semnelor de punctua\u021bie care apar \u00een pozi\u021bii corespunz\u0103toare. \u0218irurile din exemplul meu (dup\u0103 sortare) pentru algoritmul de comparare arat\u0103 astfel:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Abakanov Mihail Malar\nElkina Ella Cr\u0103noastr\u0103\nIvanova Alla Malar\nIvanov Andrei T\u0103ietor<\/code><\/pre>\n<p><\/p>\n<p>Av\u00e2nd \u00een vedere c\u0103 \u00een tabelul greut\u0103\u021bilor literele mari din limba rus\u0103 vin dup\u0103 cele mici (la nivelul trei <em>&lt;CAP&gt;<\/em> mai greu dec\u00e2t <em>&lt;MIN&gt;<\/em>), sortarea arat\u0103 absolut corect.<\/p>\n<p><\/p>\n<p>La setarea variabilei <em>LC_COLLATE=C<\/em> se \u00eencarc\u0103 un tabel special care stabile\u0219te compararea pe octe\u021bi<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">static const uint32_t collseqwc[] =\n{\n  8, 1, 8, 0x0, 0xff,\n  \/* tabelul de primul nivel *\/\n  6 * sizeof (uint32_t),\n  \/* tabelul de al doilea nivel *\/\n  7 * sizeof (uint32_t),\n  \/* tabelul de al treilea nivel *\/\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'fe', L'xff'\n};<\/code><\/pre>\n<p><\/p>\n<p>Deoarece \u00een Unicode punctul de cod pentru \u0401 este \u00eenaintea lui A, \u0219irurile sunt sortate corespunz\u0103tor.<\/p>\n<p><\/p>\n<h1 id=\"tekstovye-i-dvoichnye-tablicy\">Tabele text \u0219i binare<\/h1>\n<p><\/p>\n<p>Este evident c\u0103 compararea \u0219irurilor este o opera\u021biune extrem de frecvent\u0103, iar analiza tabelului <em>CTT<\/em> o procedur\u0103 destul de costisitoare. Pentru a optimiza accesul la tabel, ea este compilat\u0103 \u00eentr-o form\u0103 binar\u0103 cu ajutorul comenzii <em>localedef<\/em>.<\/p>\n<p><\/p>\n<p>Comanda <em>localedef<\/em> prime\u0219te ca parametri un fi\u0219ier cu tabelul caracteristicilor na\u021bionale (op\u021biunea <em>-i<\/em>), \u00een care toate simbolurile sunt reprezentate prin puncte Unicode, \u0219i un fi\u0219ier de coresponden\u021b\u0103 \u00eentre punctele Unicode \u0219i simbolurile unei anumite codific\u0103ri (op\u021biunea <em>-f<\/em>). Ca rezultat al execu\u021biei, se creeaz\u0103 fi\u0219iere binare pentru local\u0103, cu numele specificat \u00een ultimul parametru.<\/p>\n<p><\/p>\n<p><em>Glibc<\/em> suport\u0103 dou\u0103 formate de fi\u0219iere binare: &quot;tradi\u021bional&quot; \u0219i &quot;modern&quot;.<\/p>\n<p><\/p>\n<p>Formatul tradi\u021bional presupune c\u0103 numele local\u0103 este numele unui subdirector \u00een <em>\/usr\/lib\/locale\/<\/em>. \u00cen acest subdirector sunt stocate fi\u0219ierele binare <em>LC_COLLATE<\/em>, <em>LC_CTYPE<\/em>, <em>LC_TIME<\/em> etc. Fi\u0219ierul <em>LC_IDENTIFICATION<\/em> con\u021bine numele formal al localit\u0103\u021bii (care poate diferi de numele directorului) \u0219i comentarii.<\/p>\n<p><\/p>\n<p>Formatul modern presupune stocarea tuturor localelor \u00eentr-un singur arhiv\u0103 <em>\/usr\/lib\/locale\/locale-archive<\/em>, care este mapat\u0103 \u00een memoria virtual\u0103 a tuturor proceselor ce utilizeaz\u0103 <em>glibc<\/em>. Numele localei \u00een formatul modern este supus unei canoniz\u0103ri \u2014 \u00een denumirile codific\u0103rilor r\u0103m\u00e2n doar cifrele \u0219i literele, aduse la litere mici. Astfel <em>ru_RU.KOI8-R<\/em>, va fi salvat ca <em>ru_RU.koi8r<\/em>.<\/p>\n<p><\/p>\n<p>Fi\u0219ierele de intrare sunt c\u0103utate \u00een directorul curent, precum \u0219i \u00een directoarele <em>\/usr\/share\/i18n\/locales\/<\/em> \u0219i <em>\/usr\/share\/i18n\/charmaps\/<\/em> pentru fi\u0219iere <em>CTT<\/em> \u0219i fi\u0219iere de codificare, respectiv.<\/p>\n<p><\/p>\n<p>De exemplu, comanda<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">localedef -i ru_RU -f MAC-CYRILLIC ru_RU.MAC-CYRILLIC<\/code><\/pre>\n<p><\/p>\n<p>va compila fi\u0219ierul <em>\/usr\/share\/i18n\/locales\/ru_RU<\/em> folosind fi\u0219ierul de codificare <em>\/usr\/share\/i18n\/charmaps\/MAC-CYRILLIC.gz<\/em> \u0219i va salva rezultatul \u00een <em>\/usr\/lib\/locale\/locale-archive<\/em> cu numele <em>ru_RU.maccyrillic<\/em><\/p>\n<p><\/p>\n<p>Dac\u0103 se seteaz\u0103 variabila <em>LANG=en_US.UTF-8<\/em> atunci <em>glibc<\/em> va c\u0103uta fi\u0219ierele binare ale localelor \u00een urm\u0103toarea succesiune de fi\u0219iere \u0219i directoare:<\/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>Dac\u0103 local\u0103 apare at\u00e2t \u00een formate tradi\u021bionale, c\u00e2t \u0219i \u00een cele moderne, prioritatea este dat\u0103 formatului modern.<\/p>\n<p><\/p>\n<p>Pentru a vizualiza lista localelor compilate, se poate folosi comanda <em>locale -a<\/em>.<\/p>\n<p><\/p>\n<h1 id=\"podgotovka-svoey-tablicy-sravneniya\">Preg\u0103tirea propriei tabele de comparare<\/h1>\n<p><\/p>\n<p>Acum, dispun\u00e2nd de cuno\u0219tin\u021be, se poate crea propria tabel\u0103 ideal\u0103 de comparare a \u0219irurilor. Aceast\u0103 tabel\u0103 trebuie s\u0103 compare corect literele ruse\u0219ti, inclusiv litera \u0401, \u0219i s\u0103 \u021bin\u0103 cont de semnele de punctua\u021bie conform tabelei <em>ASCII<\/em>.<\/p>\n<p><\/p>\n<p>Procesul de preg\u0103tire a propriei tabele de ordonare const\u0103 \u00een dou\u0103 etape: editarea tabelei de greut\u0103\u021bi \u0219i compilarea acesteia \u00een form\u0103 binar\u0103 cu comanda <em>localedef<\/em>.<\/p>\n<p><\/p>\n<p>Pentru a ajusta tabela de comparare cu costuri minime pentru editare, \u00een formatul <em>ISO 14652<\/em> se preconizeaz\u0103 sec\u021biuni de ajustare a greut\u0103\u021bilor pentru tabelul existent. Sec\u021biunea \u00eencepe cu cuv\u00e2ntul cheie <em>reorder-after<\/em> \u0219i indicarea pozi\u021biei dup\u0103 care se efectueaz\u0103 \u00eenlocuirea. Sec\u021biunea se finalizeaz\u0103 cu linia <em>reorder-end<\/em>. Dac\u0103 trebuie s\u0103 corectez mai multe por\u021biuni ale tabelului, se creeaz\u0103 c\u00e2te o sec\u021biune pentru fiecare por\u021biune.<\/p>\n<p><\/p>\n<p>Am copiat noile versiuni ale fi\u0219ierelor <em>iso14651_t1_common<\/em> \u0219i <em>ru_RU<\/em> din depozit <em>glibc<\/em> \u00een directorul meu personal ~\/.local\/share\/i18n\/locales\/ \u0219i am editat u\u0219or sec\u021biunea <em>LC_COLLATE<\/em> \u00een <em>ru_RU<\/em>. Noile versiuni ale fi\u0219ierelor sunt complet compatibile cu versiunea mea <em>glibc<\/em>. Dac\u0103 dore\u0219ti s\u0103 folose\u0219ti versiunile vechi ale fi\u0219ierelor, va trebui s\u0103 schimbi numele simbolice \u0219i locul de unde \u00eencepe \u00eenlocuirea \u00een tabel.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">LC_COLLATE\n% Copia\u021bi \u0219ablonul din ISO\/IEC 14651\ncopia\u021bi &quot;iso14651_t1&quot;\nreordona\u021bi-dupa &lt;U000D&gt;\n&lt;U0020&gt; &lt;S0020&gt;;&lt;BASE&gt;;&lt;MIN&gt;&lt;U0020&gt; % SPATIU\n&lt;U0021&gt; &lt;S0021&gt;;&lt;BASE&gt;&lt;MIN&gt;&lt;U0021&gt; % SEMN DE \u00ceNTREBARE\n&lt;U0022&gt; &lt;S0022&gt;;&lt;BASE&gt;&lt;MIN&gt;&lt;U0022&gt; % SEMN DE \u00ceNTREBARE CITAT\n...\n&lt;U007D&gt; &lt;S007D&gt;;&lt;BASE&gt;&lt;MIN&gt;&lt;U007D&gt; % ACOLADA DREAPTA\n&lt;U007E&gt; &lt;S007E&gt;;&lt;BASE&gt;&lt;MIN&gt;&lt;U007E&gt; % TILD\u0102\nreordona\u021bi-final\nEND LC_COLLATE<\/code><\/pre>\n<p><\/p>\n<p>De fapt, ar fi trebuit s\u0103 schimb c\u00e2mpurile \u00een <em>LC_IDENTIFICATION<\/em> astfel \u00eenc\u00e2t s\u0103 indice pe localitatea <em>ru_MY<\/em>, dar \u00een exemplul meu acest lucru nu a fost necesar, deoarece am exclus din c\u0103utare arhiva localiz\u0103rilor <em>locale-archive<\/em>.<\/p>\n<p><\/p>\n<p>Pentru a <em>localedef<\/em> am lucrat cu fi\u0219iere \u00een directorul meu prin variabila <em>I18NPATH<\/em> se poate ad\u0103uga un director suplimentar pentru c\u0103utarea fi\u0219ierelor de intrare, iar directorul pentru salvarea fi\u0219ierelor binare poate fi specificat sub form\u0103 de cale cu slash-uri:<\/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> presupune c\u0103 <em>LANG<\/em> poate scrie c\u0103i absolute c\u0103tre directoarele cu fi\u0219ierele localiz\u0103rilor, \u00eencep\u00e2nd cu slash-ul direct, dar <em>glibc<\/em> \u00een <em>Linux<\/em> toate c\u0103ile sunt considerate a fi de la directorul de baz\u0103, care poate fi redefinit prin variabila <em>LOCPATH<\/em>. Dup\u0103 setarea <em>LOCPATH=~\/.local\/lib\/locale\/<\/em> toate fi\u0219ierele legate de localizare vor fi c\u0103utate doar \u00een directorul meu. Arhiva localiz\u0103rilor cu variabila setat\u0103 <em>LOCPATH<\/em> este ignorat\u0103.<\/p>\n<p><\/p>\n<p>Iat\u0103 testul decisiv:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; LANG=ru_MY.UTF-8 LOCPATH=~\/.local\/lib\/locale\/ sort buhg.txt\nAbakanov Mihail;vopsitor\nElkina Ella;crainic\u0103\nIvanov Andrei;instalator\nIvanova Alla;avocat<\/code><\/pre>\n<p><\/p>\n<p>Ura! Am reu\u0219it!<\/p>\n<p><\/p>\n<h1 id=\"rabota-nad-oshibkami\">Lucru la erori<\/h1>\n<p><\/p>\n<p>Am r\u0103spuns deja \u00eentreb\u0103rilor despre sortarea r\u00e2ndurilor, ridicate la \u00eenceput, dar mai exist\u0103 c\u00e2teva \u00eentreb\u0103ri despre erori \u2013 vizibile \u0219i invizibile.<\/p>\n<p><\/p>\n<p>S\u0103 ne \u00eentoarcem la sarcina original\u0103.<\/p>\n<p><\/p>\n<p>\u0218i programul <em>sort<\/em> \u0219i programul <em>join<\/em> folosesc acelea\u0219i func\u021bii de comparare a r\u00e2ndurilor din <em>glibc<\/em>. Cum a fost posibil c\u0103 <em>join<\/em> a returnat o eroare de sortare pe liniile sortate de comanda <em>sort<\/em> \u00een local\u0103 <em>en_US.UTF-8<\/em>? \u041e\u0442\u0432\u0435\u0442 \u043f\u0440\u043e\u0441\u0442: <em>sort<\/em> compara \u00eentreaga linie, \u00een timp ce <em>join<\/em> compara doar cheia, care \u00een mod implicit este \u00eenceputul liniei p\u00e2n\u0103 la primul caracter de spa\u021biu. \u00cen exemplul meu, acest lucru a dus la un mesaj de eroare, deoarece sortarea primelor cuvinte din linii nu s-a potrivit cu sortarea liniilor complete.<\/p>\n<p><\/p>\n<p>Locale <em>&quot;C&quot;<\/em> garanteaz\u0103 c\u0103 sub\u0219irurile ini\u021biale p\u00e2n\u0103 la primul spa\u021biu din liniile sortate vor fi de asemenea sortate, dar acest lucru doar mascheaz\u0103 eroarea. Se pot alege date de tipul (persoane cu aceea\u0219i prenume, dar nume diferite), care f\u0103r\u0103 mesaj de eroare ar da un rezultat gre\u0219it la fuziunea fi\u0219ierelor. Dac\u0103 dorim ca <em>join<\/em> s\u0103 combine liniile fi\u0219ierelor dup\u0103 nume \u0219i prenume, atunci cea mai bun\u0103 metod\u0103 este s\u0103 specific\u0103m despartitorul de c\u00e2mpuri \u0219i s\u0103 sort\u0103m dup\u0103 c\u00e2mpul cheie, nu dup\u0103 \u00eentreaga linie. \u00cen acest fel, fuziunea va decurge corect \u0219i nu vor exista erori \u00een nicio local\u0103:<\/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>Un exemplu de succes \u00een codificare <em>CP1251<\/em> con\u021bine o alt\u0103 eroare. Este vorba c\u0103 \u00een toate distribu\u021biile pe care le cunosc <em>Linux<\/em> pachetele nu con\u021bin localul compilat <em>ru_RU.CP1251<\/em>. Dac\u0103 loca\u021bia compilat\u0103 nu este g\u0103sit\u0103, atunci <em>sort<\/em> folose\u0219te \u00een t\u0103cere o compara\u021bie pe byte, ceea ce am observat.<\/p>\n<p><\/p>\n<p>Apropo, exist\u0103 o alt\u0103 mic\u0103 eroare legat\u0103 de inaccesibilitatea localurilor compilate. Comanda <em>LOCPATH=\/tmp locale -a<\/em> va returna o list\u0103 cu toate localurile din <em>locale-archive<\/em>, dar cu variabila setat\u0103 <em>LOCPATH<\/em> pentru toate programele (inclusiv pentru sinele <em>locale<\/em>) aceste localuri vor fi inaccesibile.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; LOCPATH=\/tmp locale -a | grep en_US\nlocale: Cannot set LC_CTYPE to default locale: No such file or directory\nlocale: Cannot set LC_MESSAGES to default locale: No such file or directory\nlocale: Cannot set LC_COLLATE to default locale: No such file or directory\nen_US\nen_US.iso88591\nen_US.iso885915\nen_US.utf8\n\n$&gt; LC_COLLATE=en_US.UTF-8 sort --debug\nsort: using \u2018en_US.UTF-8\u2019 sorting rules\n\n$&gt; LOCPATH=\/tmp LC_COLLATE=en_US.UTF-8 sort --debug\nsort: using simple byte comparison<\/code><\/pre>\n<p><\/p>\n<h1 id=\"zaklyuchenie\">Concluzie<\/h1>\n<p><\/p>\n<p>Dac\u0103 e\u0219ti un programator care este obi\u0219nuit s\u0103 considere c\u0103 liniile sunt un set de byte, atunci alegerea ta <em>LC_COLLATE=C<\/em>.<\/p>\n<p><\/p>\n<p>Dac\u0103 e\u0219ti un lingvist sau un compilator de dic\u021bionare, atunci cel mai bine este s\u0103 compilezi propria ta local\u0103.<\/p>\n<p><\/p>\n<p>Dac\u0103 e\u0219ti un utilizator obi\u0219nuit, atunci este suficient s\u0103 te obi\u0219nuie\u0219ti cu faptul c\u0103 comanda <em>ls -a<\/em> returneaz\u0103 fi\u0219ierele care \u00eencep cu punct, amestecate cu fi\u0219ierele care \u00eencep cu liter\u0103, iar <em>Midnight Commander<\/em>, care utilizeaz\u0103 func\u021biile interne pentru a sorta numele, mut\u0103 fi\u0219ierele care \u00eencep cu punct, la \u00eenceputul listei.<\/p>\n<p><\/p>\n<h1 id=\"ssylki\">Linkuri<\/h1>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/unicode.org\/reports\/tr10\/\">Raport Nr. 10 Algoritmul de collationare Unicode <\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"http:\/\/www.unicode.org\/Public\/UCA\/latest\/allkeys.txt\">Greut\u0103\u021bile caracterelor pe 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 implementarea unei biblioteci pentru lucrul cu Unicode de la 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 sortare folosind <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\">Greut\u0103\u021bile caracterelor \u00een <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\">Descrierea formatului fi\u0219ierului cu greut\u0103\u021bi <em>ISO 14652<\/em> <\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/sourceware.org\/bugzilla\/show_bug.cgi?id=14095\">Discu\u021bie privind compararea \u0219irurilor \u00een <em>glibc<\/em><\/a><\/noindex><\/p>\n<p>Sursa: <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.1 - 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\/ro\/blog\/administrirovanie\/kak-linuxovskij-sort-sortiruet-stroki\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"ro_RO\" \/>\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\/ro\/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\udd47Cum sorteaz\u0103 Linux 'sort' \u0219irurile | ProHoster","description":"Introducere Totul a \u00eenceput cu un scurt script, care trebuia s\u0103 uneasc\u0103 informa\u021biile despre adresele de e-mail ale angaja\u021bilor, ob\u021binute din lista utilizatorilor de mailing list, cu.","canonical_url":"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/kak-linuxovskij-sort-sortiruet-stroki","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"ro_RO","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\/ro\/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\/ro\/wp-json\/wp\/v2\/posts\/83055","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/comments?post=83055"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/83055\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media?parent=83055"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/categories?post=83055"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/tags?post=83055"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}