{"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\/it\/blog\/administrirovanie\/kak-linuxovskij-sort-sortiruet-stroki","title":{"rendered":"Come il sort di Linux ordina le stringhe","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<h1 id=\"vvedenie\">Introduzione<\/h1>\n<p><\/p>\n<p>Tutto \u00e8 iniziato con un breve script che doveva unire le informazioni sugli indirizzi <em>e-mail<\/em> dei dipendenti, ottenute da un elenco di utenti di una mailing list, con le posizioni dei dipendenti, ricavate dal database delle risorse umane. Entrambi gli elenchi erano stati esportati in file di testo in codifica Unicode <em>UTF-8<\/em> e salvati con linee finali unix.<\/p>\n<p><\/p>\n<p>Contenuto <em>mail.txt<\/em><\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Ivanov Andrey;ia@example.com<\/code><\/pre>\n<p><\/p>\n<p>Contenuto <em>buhg.txt<\/em><\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Ivanova Alla;pittore\nYelkina Ella;crane operator\nIvanov Andrey;fabbro\nAbakanov Mikhail;pittore<\/code><\/pre>\n<p><\/p>\n<p>Per unire i file, sono stati ordinati con un comando unix <em>sort<\/em> e inviati a un programma unix <em>join<\/em>, che ha terminato inaspettatamente con un errore: <\/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: non \u00e8 ordinato: Ivanov Andrey;fabbro<\/code><\/pre>\n<p><\/p>\n<p>Un'osservazione visiva del risultato dell'ordinamento ha mostrato che, in generale, l'ordinamento era corretto, ma in caso di omonimie tra cognomi maschili e femminili, i femminili precedono i maschili:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; sort buhg.txt\nAbakanov Mikhail;pittore\nYelkina Ella;crane operator\nIvanova Alla;pittore\nIvanov Andrey;fabbro<\/code><\/pre>\n<p><\/p>\n<p>Sembra un bug nell'ordinamento in Unicode o l'emergere di femminismo nell'algoritmo di ordinamento. La prima spiegazione \u00e8 certamente pi\u00f9 plausibile.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Mettiamo in sospeso <em>join<\/em> e concentriamoci su <em>sort<\/em>. Proviamo a risolvere il problema attraverso tentativi. Iniziamo cambiando la lingua in <em>en_US<\/em> con <em>ru_RU<\/em>. Per l'ordinamento sarebbe sufficiente impostare la variabile d'ambiente <em>LC_COLLATE<\/em>, ma non ci accontenteremo:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; LANG=ru_RU.UTF-8 sort buhg.txt\nAbakanov Michail;pittore\nJolkina Ella;craneista\nIvanova Alla;pittrice\nIvanov Andrej;idraulico<\/code><\/pre>\n<p><\/p>\n<p>Niente \u00e8 cambiato.<\/p>\n<p><\/p>\n<p>Proviamo a ricodificare i file in un codice a singolo 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>Di nuovo niente \u00e8 cambiato.<\/p>\n<p><\/p>\n<p>Non c'\u00e8 niente da fare, dovremo cercare una soluzione su internet. Non ci sono informazioni specifiche sulle famiglie russe, ma ci sono domande su altre stranezze nell'ordinamento. Ad esempio, c'\u00e8 questo problema: <noindex><a rel=\"nofollow\" href=\"https:\/\/serverfault.com\/questions\/95579\/unix-sort-treats-dash-characters-as-invisible\/95593\">unix sort tratta i caratteri &#8216;-&#8216; (linea) come invisibili<\/a><\/noindex>. In breve, le stringhe &quot;a-b&quot;, &quot;aa&quot;, &quot;ac&quot; si ordinano come &quot;aa&quot;, &quot;a-b&quot;, &quot;ac&quot;.<\/p>\n<p><\/p>\n<p>La risposta \u00e8 sempre la stessa: usa la locale per programmatori <em>&quot;C&quot;<\/em> e sarete felici. Proviamo:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; LANG=C sort buhg.txt\nJolkina Ella;craneista\nAbakanov Michail;pitore\nIvanov Andrej;idraulico\nIvanova Alla;avvocato<\/code><\/pre>\n<p><\/p>\n<p>Qualcosa \u00e8 cambiato. Gli Ivanov si sono sistemati nell'ordine corretto, ma Jolkina \u00e8 sparita da qualche parte. Torniamo al compito iniziale:<\/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>\u00c8 funzionato senza errori, come promesso da Internet. E nonostante ci sia \u0401\u043b\u043a\u0438\u043d nella prima riga.<\/p>\n<p><\/p>\n<p>Sembra che il problema sia risolto, ma per precauzione proviamo un'altra codifica russa \u2014 quella di 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>Il risultato della sort, strano ma vero, coincider\u00e0 con la locale <em>&quot;C&quot;<\/em>, e l'intero esempio, di conseguenza, passa senza errori. \u00c8 davvero un mistero.<\/p>\n<p><\/p>\n<p>Non amo i misteri nella programmazione, poich\u00e9 di solito nascondono errori. Dovr\u00f2 occuparmi seriamente della questione di come funziona <em>sort<\/em> e su cosa influisce <em>LC_COLLATE<\/em> .<\/p>\n<p><\/p>\n<p>Alla fine cercher\u00f2 di rispondere alle domande:<\/p>\n<p><\/p>\n<ul>\n<li>perch\u00e9 i cognomi femminili venivano ordinati in modo errato<\/li>\n<li>perch\u00e9 <em>LANG=ru_RU.CP1251<\/em> si \u00e8 rivelato equivalente <em>LANG=C<\/em><\/li>\n<li>perch\u00e9 le persone hanno <em>sort<\/em> e <em>join<\/em> visioni diverse sull'ordine delle righe ordinate<\/li>\n<li>perch\u00e9 nei miei esempi ci sono errori<\/li>\n<li>infine, come ordinare le righe secondo il proprio gusto<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"sortirovka-v-yunikode\">Ordinamento in Unicode<\/h1>\n<p><\/p>\n<p>La prima tappa sar\u00e0 il rapporto tecnico n. 10 intitolato <noindex><a rel=\"nofollow\" href=\"https:\/\/unicode.org\/reports\/tr10\/\">algoritmo di collazione Unicode<\/a><\/noindex> sul sito <noindex><a rel=\"nofollow\" href=\"https:\/\/unicode.org\">unicode.org<\/a><\/noindex>. Il rapporto contiene molti dettagli tecnici, quindi permettetemi di fornire un riassunto delle idee principali.<\/p>\n<p><\/p>\n<p><em>Collazione<\/em> \u2014 &quot;confronto&quot; di stringhe \u2014 \u00e8 alla base di ogni algoritmo di ordinamento. Gli algoritmi stessi possono variare (&quot;a bolle&quot;, &quot;a fusione&quot;, &quot;rapido&quot;), ma tutti utilizzeranno il confronto di coppie di stringhe per determinare il loro ordine.<\/p>\n<p><\/p>\n<p>L'ordinamento delle stringhe in linguaggio naturale \u00e8 un problema piuttosto complesso. Anche nelle pi\u00f9 semplici codifiche a byte singolo, l'ordine delle lettere nell'alfabeto, anche se differente dall'inglese, non corrisponder\u00e0 all'ordine dei valori numerici con cui queste lettere sono codificate. Ad esempio, nella lingua tedesca la lettera <em>\u00d6<\/em> si trova tra <em>maggiore numero di partizioni.<\/em> e <em>P<\/em>, mentre nella codifica <em>CP850<\/em> essa si colloca tra <em>\u00ff<\/em> e <em>\u00dc<\/em>.<\/p>\n<p><\/p>\n<p>Si pu\u00f2 cercare di astrarre dalla codifica specifica e considerare le &quot;lettere ideali&quot; disposte in un certo ordine, come fatto in Unicode. Le codifiche <em>UTF8<\/em>, <em>UTF16<\/em> o la codifica a byte singolo <em>KOI8-R<\/em> (se \u00e8 necessario un sottoinsieme limitato di Unicode) daranno rappresentazioni numeriche diverse delle lettere, ma facendo riferimento agli stessi elementi della tabella di base. <\/p>\n<p><\/p>\n<p>Si scopre che anche costruendo una tabella di caratteri da zero, non saremo in grado di assegnare un ordine universale ai caratteri. Nei vari alfabeti nazionali che utilizzano lettere identiche, l'ordine di queste lettere pu\u00f2 differire. Ad esempio, nella lingua francese <em>\u00c6<\/em> verr\u00e0 considerato un legatura e ordinato come una stringa <em>AE<\/em>. Nella lingua norvegese, invece, <em>\u00c6<\/em> verr\u00e0 considerata una lettera separata che si trova dopo <em>Z<\/em>. A proposito, oltre alle legature tipo <em>\u00c6<\/em> esistono lettere scritte con pi\u00f9 simboli. Cos\u00ec nell'alfabeto ceco c'\u00e8 la lettera <em>Ch<\/em>, che si colloca tra <em>H<\/em> e <em>I<\/em>.<\/p>\n<p><\/p>\n<p>Oltre alle differenze negli alfabeti, ci sono anche altre tradizioni nazionali che influenzano l'ordinamento. In particolare, sorge la questione: in quale ordine dovrebbero seguire nel dizionario le parole composte da lettere maiuscole e minuscole? Inoltre, l'ordinamento pu\u00f2 essere influenzato dalle peculiarit\u00e0 dell'uso della punteggiatura. Nella lingua spagnola, all'inizio di una frase interrogativa viene inserito un punto interrogativo rovesciato (<em>\u00bfTe gusta la m\u00fasica?<\/em>). In questo caso \u00e8 chiaro che le frasi interrogative non devono essere raggruppate in un cluster separato dall'alfabeto, quindi come dovrebbero essere ordinate le stringhe con altri segni di punteggiatura?<\/p>\n<p><\/p>\n<p>Non mi fermer\u00f2 a discutere dell'ordinamento delle stringhe in lingue molto diverse da quelle europee. Vorrei sottolineare che in lingue con direzione di scrittura da destra a sinistra o dall'alto verso il basso, i simboli nelle stringhe sono probabilmente conservati nell'ordine di lettura, e anche in scritture non alfabetiche esistono modi per ordinare le stringhe simbolo per simbolo. Ad esempio, i caratteri possono essere ordinati in base alla loro forma (<noindex><a rel=\"nofollow\" href=\"https:\/\/studychinese.ru\/kljuchi\/\">chiavi dei caratteri cinesi<\/a><\/noindex>) o in base alla pronuncia. Non ho idea di come dovrebbero essere ordinati gli emoji, ma si pu\u00f2 sicuramente trovare una soluzione anche per loro.<\/p>\n<p><\/p>\n<p>Sulla base delle caratteristiche sopra menzionate, sono stati formulati i requisiti principali per il confronto delle stringhe, basati sulle tabelle Unicode:<\/p>\n<p><\/p>\n<ul>\n<li>il confronto delle stringhe non dipende dalla posizione dei caratteri nella tabella dei codici;<\/li>\n<li>le sequenze di caratteri che formano un unico carattere vengono portate alla forma canonica (<em>A<\/em> + il cerchietto superiore \u00e8 lo stesso di <em>\u00c5<\/em>);<\/li>\n<li>Quando si confrontano le stringhe, il carattere viene considerato nel contesto della stringa e, se necessario, viene combinato con i vicini in un'unit\u00e0 di confronto (<em>Ch<\/em> in ceco) oppure viene suddiviso in pi\u00f9 parti (<em>\u00c6<\/em> in francese);<\/li>\n<li>tutte le peculiarit\u00e0 nazionali (alfabeto, maiuscole\/minuscole, punteggiatura, ordine dei tipi di scrittura) devono essere configurabili fino a una specifica assegnazione dell'ordine (emoji);<\/li>\n<li>il confronto \u00e8 importante non solo per l'ordinamento, ma anche in molte altre aree, ad esempio per impostare intervalli di stringhe (sostituzione {A\u2026 \u044f} in <em>bash<\/em>);<\/li>\n<li>il confronto deve essere eseguito abbastanza rapidamente.<\/li>\n<\/ul>\n<p><\/p>\n<p>Inoltre, gli autori del rapporto hanno delineato le propriet\u00e0 del confronto su cui gli sviluppatori dell'algoritmo non dovrebbero fare affidamento:<\/p>\n<p><\/p>\n<ul>\n<li>l'algoritmo di confronto non dovrebbe richiedere un insieme separato di caratteri per ogni lingua (le lingue russa e ucraina condividono la maggior parte dei caratteri cirillici);<\/li>\n<li>il confronto non dovrebbe basarsi sull'ordine dei caratteri nelle tabelle Unicode;<\/li>\n<li>il peso della stringa non dovrebbe essere un attributo della stringa, poich\u00e9 la stessa stringa in diversi contesti culturali pu\u00f2 avere pesi diversi;<\/li>\n<li>il peso delle stringhe pu\u00f2 variare durante la fusione o la divisione (da <em>x<\/em> &lt; <em>y<\/em> non implica che <em>xz<\/em> &lt; <em>yz<\/em>);<\/li>\n<li>stringhe diverse con lo stesso peso siano considerate uguali secondo l'algoritmo di ordinamento. Introdurre un ulteriore ordinamento di tali stringhe \u00e8 possibile, ma potrebbe ridurre le prestazioni;<\/li>\n<li>nelle ri-ordinazioni, le stringhe con lo stesso peso possono scambiarsi di posto. La stabilit\u00e0 \u00e8 una propriet\u00e0 di un particolare algoritmo di ordinamento, non una propriet\u00e0 dell'algoritmo di confronto delle stringhe (vedi punto precedente);<\/li>\n<li>le regole di ordinamento possono cambiare nel tempo man mano che le tradizioni culturali vengono affinabili\/cambiate.<\/li>\n<\/ul>\n<p><\/p>\n<p>Si specifica inoltre che l'algoritmo di confronto non sa nulla circa la semantica delle stringhe elaborate. Pertanto, stringhe costituite soltanto da cifre non devono essere confrontate come numeri, e negli elenchi di nomi inglesi non deve essere rimosso l'articolo (<em>Beatles, The<\/em>).<\/p>\n<p><\/p>\n<p>Per soddisfare tutti i requisiti indicati, \u00e8 stato proposto un algoritmo di ordinamento tabellare multilivello (in effetti a quattro livelli).<\/p>\n<p><\/p>\n<p>All'inizio, i caratteri nella stringa vengono normalizzati e raggruppati in unit\u00e0 di confronto. A ciascuna unit\u00e0 di confronto sono assegnati diversi pesi, corrispondenti a vari livelli di confronto. I pesi delle unit\u00e0 di confronto sono elementi di insiemi ordinati (in questo caso numeri interi), che possono essere confrontati tra loro. <em>IGNORATO<\/em> (0x0) indica che a quel livello di confronto, l'unit\u00e0 corrispondente non partecipa. Il confronto delle stringhe pu\u00f2 essere ripetuto pi\u00f9 volte, utilizzando i pesi dei livelli appropriati. A ciascun livello, i pesi delle unit\u00e0 di confronto delle due stringhe vengono confrontati sequenzialmente.<\/p>\n<p><\/p>\n<p>Nelle varie implementazioni dell'algoritmo, per diverse tradizioni nazionali, i valori dei coefficienti possono variare, ma nel standard Unicode \u00e8 inclusa una tabella base dei pesi \u2014 <em>&quot;Default Unicode Collation Element Table&quot;<\/em> (<em>DUCET<\/em>). Vorrei sottolineare che l'impostazione della variabile <em>LC_COLLATE<\/em> \u00e8 in realt\u00e0 un'indicazione per la scelta della tabella dei pesi nella funzione di confronto delle stringhe.<\/p>\n<p><\/p>\n<p>I coefficienti di peso <em>DUCET<\/em> sono strutturati come segue:<\/p>\n<p><\/p>\n<ul>\n<li>al primo livello tutte le lettere vengono portate a un'unica maiuscola, i segni diacritici vengono ignorati, la punteggiatura (non tutta) viene trascurata;<\/li>\n<li>al secondo livello vengono considerati solo i segni diacritici;<\/li>\n<li>al terzo livello viene considerato solo il maiuscolo e il minuscolo;<\/li>\n<li>al quarto livello vengono considerati solo i segni di punteggiatura.<\/li>\n<\/ul>\n<p><\/p>\n<p>Il confronto avviene in pi\u00f9 passaggi: prima vengono confrontati i coefficienti di primo livello; se i pesi coincidono, si procede a un confronto ripetuto con i pesi di secondo livello; poi, eventualmente, di terzo e quarto.<\/p>\n<p><\/p>\n<p>Il confronto termina quando nelle stringhe sono presenti unit\u00e0 di confronto corrispondenti con pesi diversi. Le stringhe che hanno pesi uguali a tutti i quattro livelli sono considerate equivalenti tra loro.<\/p>\n<p><\/p>\n<p>Questo algoritmo (con un sacco di dettagli tecnici aggiuntivi) ha dato il nome al rapporto n. 10 \u2014 <em>&quot;Unicode Collation Algorithm&quot;<\/em> (<em>UCA<\/em>).<\/p>\n<p><\/p>\n<p>In questo punto il comportamento dell'ordinamento del nostro esempio diventa un po' pi\u00f9 chiaro. Sarebbe utile confrontarlo con lo standard Unicode.<\/p>\n<p><\/p>\n<p>Per testare le implementazioni <em>UCA<\/em> esiste un <noindex><a rel=\"nofollow\" href=\"https:\/\/www.unicode.org\/Public\/UCA\/latest\/CollationTest.html\">test<\/a><\/noindex>, che utilizza <noindex><a rel=\"nofollow\" href=\"http:\/\/www.unicode.org\/Public\/UCA\/latest\/allkeys.txt\">un file di pesi<\/a><\/noindex>, implementando <em>DUCET<\/em>. Nel file dei pesi si possono trovare diverse curiosit\u00e0. Ad esempio, ci sono l'ordine delle tessere del mahjong e del domino europeo, cos\u00ec come l'ordine dei semi nel mazzo di carte (simbolo <em>1F000<\/em> e cos\u00ec via). I semi delle carte sono disposti secondo le regole del bridge \u2014 PCHBT, e le carte nei semi \u2014 in sequenza A, 2, 3... K.<\/p>\n<p><\/p>\n<p>La verifica manuale della correttezza dell'ordinamento delle stringhe secondo <em>DUCET<\/em> sarebbe stata piuttosto faticosa, ma, per nostra fortuna, esiste un'implementazione esemplare della libreria per lavorare con Unicode \u2014 &quot;<noindex><a rel=\"nofollow\" href=\"http:\/\/site.icu-project.org\/\">International Components for Unicode<\/a><\/noindex>&quot; (<em>ICU<\/em>).<\/p>\n<p><\/p>\n<p>Sul sito di questa libreria, sviluppata in <em>IBM<\/em>, ci sono pagine dimostrative, inclusa la <noindex><a rel=\"nofollow\" href=\"http:\/\/demo.icu-project.org\/icu-bin\/collation.html\">pagina dell'algoritmo di confronto delle stringhe<\/a><\/noindex>. Introduciamo le nostre stringhe di test con le impostazioni predefinite e, oh meraviglia, otteniamo un'ordinamento russo perfetto.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Abakanov Mikhail;pittore\nYolkina Ella;gruista\nIvanov Andrey;fabbro\nIvanova Alla;avvocato<\/code><\/pre>\n<p><\/p>\n<p>A proposito, sul sito <em>ICU<\/em> si pu\u00f2 trovare chiarimenti sul funzionamento dell'algoritmo di confronto nella gestione dei segni di punteggiatura. Negli esempi <noindex><a rel=\"nofollow\" href=\"http:\/\/userguide.icu-project.org\/collation\/faq\">Collation FAQ<\/a><\/noindex> viene ignorata l'apostrofo e il trattino.<\/p>\n<p><\/p>\n<p>Unicode ci ha aiutato, ma bisogner\u00e0 cercare le ragioni del comportamento strano <em>sort<\/em> in <em>Linux<\/em> in un altro posto.<\/p>\n<p><\/p>\n<h1 id=\"sortirovka-v-glibc\">Ordinamento in glibc<\/h1>\n<p><\/p>\n<p>Anteprima del codice sorgente dell'utility <em>sort<\/em> di <em>GNU Core Utils<\/em> ha dimostrato che all'interno dell'utility la localizzazione si limita alla stampa del valore corrente della variabile <em>LC_COLLATE<\/em> quando eseguita in modalit\u00e0 di debug:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$ sort --debug buhg.txt &gt; buhg.srt\nsort: utilizza le regole di ordinamento \u2018en_US.UTF8\u2019<\/code><\/pre>\n<p><\/p>\n<p>Il confronto delle stringhe avviene tramite la funzione standard <em>strcoll<\/em>, il che significa che tutto l'interessante si trova nella libreria <em>glibc<\/em>.<\/p>\n<p><\/p>\n<p>Su <em>wiki<\/em> progetto <em>glibc<\/em> dedicata al confronto delle stringhe <noindex><a rel=\"nofollow\" href=\"https:\/\/sourceware.org\/glibc\/wiki\/Locales#LC_COLLATE\">un paragrafo<\/a><\/noindex>. Da questo paragrafo possiamo capire che la <em>glibc<\/em> l'ordinamento si basa su un algoritmo gi\u00e0 noto <em>UCA<\/em> (<em>The Unicode collation algorithm<\/em>) e\/o su uno standard a esso simile <em>ISO 14651<\/em> (<em>Ordinamento e confronto delle stringhe internazionali<\/em>). A proposito dell'ultimo standard, va notato che sul sito <noindex><a rel=\"nofollow\" href=\"https:\/\/standards.iso.org\/ittf\/PubliclyAvailableStandards\">standards.iso.org<\/a><\/noindex> <em>ISO 14651<\/em> \u00e8 ufficialmente dichiarato pubblico, ma il link corrispondente porta a una pagina inesistente. Google mostra diverse pagine con collegamenti ai siti ufficiali che offrono di acquistare una copia elettronica dello standard per un centinaio di euro, ma nelle terze o quarte pagine dei risultati di ricerca si possono trovare anche link diretti a <em>PDF<\/em>. In generale, lo standard non \u00e8 praticamente diverso da <em>UCA<\/em>, ma si legge in modo pi\u00f9 noioso, poich\u00e9 non contiene esempi vividi delle particolarit\u00e0 nazionali dell'ordinamento delle stringhe. <\/p>\n<p><\/p>\n<p>Le informazioni pi\u00f9 interessanti su <em>wiki<\/em> si sono rivelate essere il link a <noindex><a rel=\"nofollow\" href=\"https:\/\/sourceware.org\/bugzilla\/show_bug.cgi?id=14095\">un tracker di bug<\/a><\/noindex> con una discussione sull'implementazione del confronto delle stringhe in <em>glibc<\/em>. Dalla discussione si pu\u00f2 apprendere che in <em>glibc<\/em> per il confronto delle stringhe si utilizza <em>ISO<\/em>una tabella comune <noindex><a rel=\"nofollow\" href=\"http:\/\/www.iso.org\/ittf\/ISO14651_2006_TABLE1_en.txt\">The Common Template Table<\/a><\/noindex> (<em>CTT<\/em>), il cui indirizzo pu\u00f2 essere trovato nell'applicazione <em>A<\/em> del standard <em>ISO 14651<\/em>. Tra il 2000 e il 2015 questa tabella in <em>glibc<\/em> non aveva un maintainer ed era abbastanza differente (almeno esteticamente) dall'attuale versione standard. Dal 2015 al 2018 c'\u00e8 stata un'adattamento alla nuova versione della tabella e attualmente si pu\u00f2 incontrare nella vita reale sia la nuova versione della tabella (<em>CentOS 8<\/em>), sia la vecchia (<em>CentOS 7<\/em>). <\/p>\n<p><\/p>\n<p>Ora che abbiamo tutte le informazioni sugli algoritmi e le tabelle ausiliarie, possiamo tornare al problema iniziale e capire come ordinare correttamente le stringhe nella locale russa.<\/p>\n<p><\/p>\n<h1 id=\"iso-1465114652\">ISO 14651\u204414652<\/h1>\n<p><\/p>\n<p>Il codice sorgente della tabella che ci interessa <em>CTT<\/em> si trova nella maggior parte delle distribuzioni <em>Linux<\/em> nella directory <em>\/usr\/share\/i18n\/locales\/<\/em>. La tabella stessa si trova nel file <em>iso14651_t1_common<\/em>. Poi questo file viene incluso nella direttiva <em>copy iso14651_t1_common<\/em> inclusa nel file <em>iso14651_t1<\/em>, che a sua volta \u00e8 incluso nei file nazionali, compresi i <em>en_US<\/em> e <em>ru_RU<\/em>. Nella maggior parte delle distribuzioni <em>Linux<\/em> tutti i file sorgente sono inclusi nell'installazione di base, ma se non sono presenti, sar\u00e0 necessario installare un pacchetto aggiuntivo dal distributore.<\/p>\n<p><\/p>\n<p>La struttura del file <em>iso14651_t1<\/em> pu\u00f2 sembrare terribilmente verbose, con regole di nomenclatura poco ovvie, ma una volta compreso, \u00e8 tutto piuttosto semplice. La struttura \u00e8 descritta nello standard <em>ISO 14652<\/em>, una copia del quale pu\u00f2 essere scaricata dal sito <noindex><a rel=\"nofollow\" href=\"http:\/\/www.open-std.org\/JTC1\/SC22\/WG20\/docs\/n972-14652ft.pdf\">open-std.org<\/a><\/noindex>. Un'altra descrizione del formato file pu\u00f2 essere letta in <noindex><a rel=\"nofollow\" href=\"https:\/\/pubs.opengroup.org\/onlinepubs\/9699919799\/basedefs\/V1_chap07.html\">specifiche<\/a><\/noindex> <em>POSIX<\/em> da <em>OpenGroup<\/em>. In alternativa alla lettura dello standard, si possono esaminare i sorgenti della funzione <em>collate_read<\/em> in <em>glibc\/locale\/programs\/ld-collate.c<\/em>.<\/p>\n<p><\/p>\n<p>La struttura del file appare come segue:<\/p>\n<p><\/p>\n<p>Per impostazione predefinita, il simbolo viene utilizzato come carattere di escape, e la fine della linea dopo il simbolo # \u00e8 un commento. Entrambi i simboli possono essere sovrascritti, come fatto nella nuova versione della tabella:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">escape_char \/\ncomment_char %<\/code><\/pre>\n<p><\/p>\n<p>Nel file si incontreranno token nel formato <em>&lt;Uxxxx&gt;<\/em> o <em>&lt;Uxxxxxxxx&gt;<\/em> (dove <em>x<\/em> \u2014 cifra esadecimale). Questa \u00e8 la rappresentazione esadecimale dei punti codice Unicode in codifica <em>UCS-4<\/em> (<em>UTF-32<\/em>). Tutti gli altri elementi tra parentesi angolari (incluso <em>&lt;Uxxxx_xxxx&gt;<\/em>, <em>&lt;2&gt;<\/em> e simili) sono considerati costanti di stringa semplici, senza alcun significato particolare al di fuori del contesto.<\/p>\n<p><\/p>\n<p>Stringa <em>LC_COLLATE<\/em> ci dice che in seguito iniziano i dati che descrivono il confronto delle stringhe.<\/p>\n<p><\/p>\n<p>Inizialmente vengono impostati i nomi per i pesi nella tabella di confronto e i nomi per le combinazioni di caratteri. In generale, due tipi di nomi appartengono a due entit\u00e0 diverse, ma nel file reale sono mescolati. I nomi dei pesi sono impostati dalla parola chiave <em>collating-symbol<\/em> (simbolo di confronto), poich\u00e9 nel confronto i caratteri Unicode che hanno lo stesso peso saranno considerati simboli equivalenti.<\/p>\n<p><\/p>\n<p>La lunghezza totale della sezione nella revisione attuale del file \u00e8 di circa 900 righe. Ho estratto esempi da pi\u00f9 luoghi per dimostrare l'arbitrariet\u00e0 dei nomi e diversi tipi di sintassi.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">LC_COLLATE\n\ncollating-symbol &lt;RES-1&gt;\ncollating-symbol &lt;BLK&gt;\ncollating-symbol &lt;MIN&gt;\ncollating-symbol &lt;WIDE&gt;\n...\ncollating-symbol &lt;ARABIC&gt;\ncollating-symbol &lt;ETHPC&gt;\ncollating-symbol &lt;OSMANYA&gt;\n...\ncollating-symbol &lt;S1D000&gt;..&lt;S1D35F&gt;\ncollating-symbol &lt;SFFFF&gt; % Garantito valore simbolo pi\u00f9 grande. Mantieni alla fine di questo elenco\n...\ncollating-element &lt;U0413_0301&gt; da &quot;&lt;U0413&gt;&lt;U0301&gt;&quot;\ncollating-element &lt;U0413_0341&gt; da &quot;&lt;U0413&gt;&lt;U0341&gt;&quot;<\/code><\/pre>\n<p><\/p>\n<ul>\n<li><em>collating-symbol<\/em> registra la stringa <em>OSMANYA<\/em> nella tabella dei nomi dei pesi <\/li>\n<li><em>collating-symbol ..<\/em> registra una sequenza di nomi, composta da un prefisso <em>S<\/em> e un suffisso numerico esadecimale da <em>1D000<\/em> fino a <em>1D35F<\/em>.<\/li>\n<li><em>FFFF<\/em> in <em>collating-symbol<\/em> sembra un grande intero senza segno in forma esadecimale, ma <em>&lt;SFFFF&gt;<\/em> \u00e8 solo un nome che potrebbe apparire come <em>&lt;VERYBIGVAL&gt;<\/em> <\/li>\n<li>nome <em>&lt;U0413&gt;<\/em> indica un punto di codice in codifica <em>UCS-4<\/em><\/li>\n<li><em>collating-element &lt;U0413_0301&gt; da &quot;&lt;U0413&gt;&lt;U0301&gt;&quot;<\/em> registra un nuovo nome per una coppia di punti Unicode. <\/li>\n<\/ul>\n<p><\/p>\n<p>Quando i nomi dei pesi sono definiti, vengono assegnati i pesi stessi. Poich\u00e9 nel confronto conta solo la relazione maggiore-minore, i pesi sono determinati da una semplice sequenza di riferimento ai nomi. Per primi si elencano i pesi pi\u00f9 &amp;quot leggeri&quot;, poi i pi\u00f9 &quot;pesanti&quot;. Ricordo che a ciascun simbolo Unicode vengono assegnati quattro pesi diversi. Qui sono riuniti in un'unica sequenza ordinata. Teoricamente, qualsiasi nome simbolico pu\u00f2 essere utilizzato a uno dei quattro livelli, ma i commenti indicano che gli sviluppatori mentalmente dividono i nomi per livelli.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">% Assegnazioni di peso simbolico\n\n% Assegnazioni di peso di terzo livello\n\n\n\n\n...\n% Assegnazioni di peso di secondo livello\n\n % COMBINING LOW LINE\n % COMBINING COMMA ABOVE\n % COMBINING REVERSED COMMA ABOVE\n...\n% Assegnazioni di peso di primo livello\n % TABULAZIONE ORIZZONTALE\n % CR LF\n % TABULAZIONE VERTICALE\n...\n % LETTERA CILRILLICA MINUSCOLA DE\n % LETTERA CILRILLICA MINUSCOLA KOMI DE\n % LETTERA CILRILLICA MINUSCOLA DJE\n % LETTERA CILRILLICA MINUSCOLA KOMI DJE\n % LETTERA CILRILLICA MINUSCOLA GJE\n % LETTERA CILRILLICA MINUSCOLA ZE CON DISCENDENTE\n % LETTERA CILRILLICA MINUSCOLA IE\n % LETTERA CILRILLICA MINUSCOLA IE CON BREVE\n % LETTERA CILRILLICA MINUSCOLA IE UCRAINA\n % LETTERA CILRILLICA MINUSCOLA ZHE<\/code><\/pre>\n<p><\/p>\n<p>Infine, la tabella dei pesi vera e propria.<\/p>\n<p><\/p>\n<p>La sezione dei pesi \u00e8 racchiusa in righe con parole chiave <em>order_start<\/em> e <em>order_end<\/em>. Parametri aggiuntivi <em>order_start<\/em> definiscono in quale direzione vengono visualizzate le righe a ogni livello di confronto. Per impostazione predefinita, viene utilizzato il parametro <em>forward<\/em>. Il corpo della sezione \u00e8 composto da righe che contengono il codice del simbolo e i suoi quattro pesi. Il codice del simbolo pu\u00f2 essere rappresentato dal simbolo stesso, dal punto di codice o da un nome simbolico definito in precedenza. I pesi possono essere anch'essi definiti tramite nomi simbolici, punti di codice o simboli stessi. Quando si utilizzano punti di codice o simboli, il loro peso corrisponde al valore numerico del punto di codice (posizione nella tabella Unicode). I simboli non specificati esplicitamente (per come capisco) sono considerati associati nella tabella con un peso primario corrispondente alla loro posizione nella tabella Unicode. Valore speciale del peso <em>IGNORE<\/em> indica che a quel livello di confronto il simbolo corrispondente viene ignorato.<\/p>\n<p><\/p>\n<p>Per dimostrare la struttura dei pesi, ho scelto tre frammenti abbastanza evidenti:<\/p>\n<p><\/p>\n<ul>\n<li>simboli che vengono completamente ignorati<\/li>\n<li>simboli equivalenti al numero tre nei primi due livelli<\/li>\n<li>inizio dell'alfabeto cirillico, che non contiene segni diacritici e quindi viene ordinato, principalmente, in base al primo e al terzo livello.<\/li>\n<\/ul>\n<p><\/p>\n<pre><code class=\"plaintext\">ordine_inizio forward;forward;forward;forward,posizione\n IGNORARE;IGNORARE;IGNORARE;IGNORARE % NULL (in 6429)\n IGNORARE;IGNORARE;IGNORARE;IGNORARE % INIZIO INTITOLAZIONE (in 6429)\n IGNORARE;IGNORARE;IGNORARE;IGNORARE % INIZIO TESTO (in 6429)\n...\n ;;; % CIFRA TRE\n ;;; % CIFRA TRE A LARGHEZZA COMPLETA\n ;;; % CIFRA TRE TRA CITTADINI\n ;;; % CIFRA TRE PUNTO FINALE\n ;;<FONT>; % CIFRA TRE BOLD MATEMATICO\n...\n ;;; % LETTERA PICCOLA CYRILLICA A\n ;;; % LETTERA MAIUSCOLA CYRILLICA A\n ;;; % LETTERA PICCOLA CYRILLICA A CON BREVE\n ;;; % LETTERA PICCOLA CYRILLICA A CON BREVE\n...\n ;;; % LETTERA PICCOLA CYRILLICA BE\n ;;; % LETTERA MAIUSCOLA CYRILLICA BE\n ;;; % LETTERA PICCOLA CYRILLICA VE\n ;;; % LETTERA MAIUSCOLA CYRILLICA VE\n...\nordine_fine<\/code><\/pre>\n<p><\/p>\n<p>Ora \u00e8 possibile tornare a ordinare gli esempi dall'inizio dell'articolo. La trappola si nasconde in questa parte della tabella dei pesi:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">IGNORARE;IGNORARE;IGNORARE; % SPAZIO\n IGNORARE;IGNORARE;IGNORARE; % PUNTO ESCLAMATIVO\n IGNORARE;IGNORARE;IGNORARE; % VIRGOLA<\/code><\/pre>\n<p><\/p>\n<p>\u00c8 evidente che in questa tabella i segni di punteggiatura sono presenti nella tabella <em>Rasterizzazione bit per bit o byte per byte<\/em> (compreso lo spazio) durante il confronto delle stringhe vengono praticamente sempre ignorati. L'eccezione \u00e8 data solo dalle stringhe che coincidono in tutto, tranne che per i segni di punteggiatura presenti nelle posizioni corrispondenti. Le stringhe del mio esempio (dopo l'ordinamento) per l'algoritmo di confronto appaiono cos\u00ec:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">AbakanovMikhailpittore\nYolkinaEllaoperaia\nIvanovaAlalpittore\nIvanovAndreyfalegname<\/code><\/pre>\n<p><\/p>\n<p>Considerando che nella tabella di ordinamento le lettere maiuscole in russo vengono dopo quelle minuscole (al terzo livello <em>&lt;CAP&gt;<\/em> pi\u00f9 pesante di <em>&lt;MIN&gt;<\/em>), l'ordinamento appare assolutamente corretto.<\/p>\n<p><\/p>\n<p>Quando si imposta la variabile <em>LC_COLLATE=C<\/em> viene caricata una tabella speciale che definisce il confronto byte per byte<\/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'fe', L'xff'\n};<\/code><\/pre>\n<p><\/p>\n<p>Poich\u00e9 nel Unicode il punto di codice \u0401 viene prima di \u0410, le stringhe vengono ordinate di conseguenza.<\/p>\n<p><\/p>\n<h1 id=\"tekstovye-i-dvoichnye-tablicy\">Tabelle testuali e binarie<\/h1>\n<p><\/p>\n<p>\u00c8 chiaro che il confronto delle stringhe \u00e8 un'operazione estremamente comune, mentre l'analisi della tabella <em>CTT<\/em> \u00e8 un processo piuttosto costoso. Per ottimizzare l'accesso alla tabella, essa viene compilata in forma binaria dalla comando <em>localedef<\/em>.<\/p>\n<p><\/p>\n<p>Team <em>localedef<\/em> che accetta come parametri un file con la tabella delle caratteristiche nazionali (opzione <em>-i<\/em>), in cui tutti i caratteri sono rappresentati da punti Unicode, e un file di corrispondenza dei punti Unicode ai caratteri di una specifica codifica (opzione <em>-f<\/em>). Al termine del processo, vengono creati file binari per la localit\u00e0, con il nome specificato nell'ultimo parametro.<\/p>\n<p><\/p>\n<p><em>Glibc<\/em> supporta due formati di file binari: &quot;tradizionale&quot; e &quot;moderno&quot;.<\/p>\n<p><\/p>\n<p>Il formato tradizionale implica che il nome della localit\u00e0 sia il nome di una sottodirectory in <em>\/usr\/lib\/locale\/<\/em>. In questa sottodirectory vengono memorizzati i file binari <em>LC_COLLATE<\/em>, <em>LC_CTYPE<\/em>, <em>LC_TIME<\/em> e cos\u00ec via. Il file <em>LC_IDENTIFICATION<\/em> contiene il nome formale della localit\u00e0 (che pu\u00f2 differire dal nome della directory) e commenti.<\/p>\n<p><\/p>\n<p>Il formato moderno prevede la memorizzazione di tutte le localit\u00e0 in un unico archivio <em>\/usr\/lib\/locale\/locale-archive<\/em>, che viene mappato nella memoria virtuale di tutti i processi che lo utilizzano. <em>glibc<\/em>. Il nome della locale nel formato moderno subisce una certa canonizzazione \u2014 nei nomi delle codifiche rimangono solo numeri e lettere, convertiti in minuscolo. Cos\u00ec <em>ru_RU.KOI8-R<\/em>, sar\u00e0 salvato come <em>ru_RU.koi8r<\/em>.<\/p>\n<p><\/p>\n<p>I file di input sono cercati nella directory attuale, cos\u00ec come nelle directory <em>\/usr\/share\/i18n\/locales\/<\/em> e <em>\/usr\/share\/i18n\/charmaps\/<\/em> per i file <em>CTT<\/em> e per i file di codifica rispettivamente.<\/p>\n<p><\/p>\n<p>Ad esempio, il comando<\/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>compiler\u00e0 il file <em>\/usr\/share\/i18n\/locales\/ru_RU<\/em> utilizzando il file di codifica <em>\/usr\/share\/i18n\/charmaps\/MAC-CYRILLIC.gz<\/em> e salver\u00e0 il risultato in <em>\/usr\/lib\/locale\/locale-archive<\/em> con il nome <em>ru_RU.maccyrillic<\/em><\/p>\n<p><\/p>\n<p>Se si imposta la variabile <em>LANG=en_US.UTF-8<\/em> allora <em>glibc<\/em> cercher\u00e0 i file binari della locale nella seguente sequenza di file e directory:<\/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>Se la locale si trova sia nei formati tradizionali che in quelli moderni, si d\u00e0 priorit\u00e0 a quello moderno.<\/p>\n<p><\/p>\n<p>Per visualizzare l'elenco delle locale compilate, \u00e8 possibile utilizzare il comando <em>locale -a<\/em>.<\/p>\n<p><\/p>\n<h1 id=\"podgotovka-svoey-tablicy-sravneniya\">Preparare la propria tabella di confronto<\/h1>\n<p><\/p>\n<p>Ora, armati della conoscenza, puoi creare la tua tabella di confronto ideale. Questa tabella dovrebbe confrontare correttamente le lettere russe, inclusa la lettera \u0401, e tenere conto della punteggiatura in conformit\u00e0 con la tabella. <em>Rasterizzazione bit per bit o byte per byte<\/em>.<\/p>\n<p><\/p>\n<p>Il processo di preparazione della propria tabella di ordinamento si compone di due fasi: la modifica della tabella dei pesi e la sua compilazione in forma binaria mediante un comando. <em>localedef<\/em>.<\/p>\n<p><\/p>\n<p>Affinch\u00e9 la tabella di confronto possa essere adattata con costi minimi di modifica, viene utilizzato il formato <em>ISO 14652<\/em> che prevede sezioni di correzione dei pesi per una tabella esistente. La sezione inizia con la parola chiave <em>reorder-after<\/em> e l'indicazione della posizione dopo la quale avviene la sostituzione. La sezione \u00e8 conclusa dalla riga <em>reorder-end<\/em>. Se \u00e8 necessario correggere pi\u00f9 sezioni della tabella, si crea una sezione per ciascuna di esse.<\/p>\n<p><\/p>\n<p>Ho copiato le nuove versioni dei file <em>iso14651_t1_common<\/em> e <em>ru_RU<\/em> dal repository <em>glibc<\/em> nella mia cartella home ~\/.local\/share\/i18n\/locales\/ e ho modificato leggermente la sezione <em>LC_COLLATE<\/em> in <em>ru_RU<\/em>. Le nuove versioni dei file sono completamente compatibili con la mia versione <em>glibc<\/em>. Se desiderate utilizzare le versioni precedenti dei file, dovrete modificare i nomi simbolici e il luogo da cui inizia la sostituzione nella tabella.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">LC_COLLATE\n% Copia il template da ISO\/IEC 14651\ncopia &quot;iso14651_t1&quot;\nriordina dopo &lt;U000D&gt;\n&lt;U0020&gt; &lt;S0020&gt;;&lt;BASE&gt;;&lt;MIN&gt;&lt;U0020&gt; % SPAZIO\n&lt;U0021&gt; &lt;S0021&gt;;&lt;BASE&gt;&lt;MIN&gt;&lt;U0021&gt; % PUNTO ESCLAMATIVO\n&lt;U0022&gt; &lt;S0022&gt;;&lt;BASE&gt;&lt;MIN&gt;&lt;U0022&gt; % VIRGOLETTA\n...\n&lt;U007D&gt; &lt;S007D&gt;;&lt;BASE&gt;&lt;MIN&gt;&lt;U007D&gt; % PUNTO CURIOSO DESTRO\n&lt;U007E&gt; &lt;S007E&gt;;&lt;BASE&gt;&lt;MIN&gt;&lt;U007E&gt; % TILDE\nriordina fine\nFINE LC_COLLATE<\/code><\/pre>\n<p><\/p>\n<p>In realt\u00e0, sarebbe stato meglio cambiare i campi in <em>LC_IDENTIFICATION<\/em> in modo che puntassero alla locale <em>it_MY<\/em>, ma nel mio esempio non era necessario, poich\u00e9 ho escluso dalla ricerca le locali dell'archivio <em>locale-archive<\/em>.<\/p>\n<p><\/p>\n<p>Per creare un file di esportazione del database di gestione sul server di origine: <em>localedef<\/em> lavorava con i file nella mia cartella tramite la variabile <em>I18NPATH<\/em> puoi aggiungere una directory aggiuntiva per cercare i file di input, mentre la directory per salvare i file binari pu\u00f2 essere specificata come percorso con le barre:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; I18NPATH=~\/.local\/share\/i18n localedef -i it_IT -f UTF-8 ~\/.local\/lib\/locale\/it_MY.UTF-8<\/code><\/pre>\n<p><\/p>\n<p><em>POSIX<\/em> presuppone che in <em>LANG<\/em> possono essere scritti percorsi assoluti alle directory con i file di locale che iniziano con una barra, ma <em>glibc<\/em> in <em>Linux<\/em> tutti i percorsi sono calcolati dalla directory base, che pu\u00f2 essere sovrascritta tramite la variabile <em>LOCPATH<\/em>. Dopo aver impostato <em>LOCPATH=~\/.local\/lib\/locale\/<\/em> tutti i file correlati alla localizzazione verranno cercati solo nella mia cartella. L'archivio delle locali con la variabile impostata <em>LOCPATH<\/em> viene ignorata.<\/p>\n<p><\/p>\n<p>Ecco il test decisivo:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; LANG=it_IT.UTF-8 LOCPATH=~\/.local\/lib\/locale\/ sort buhg.txt\nAbakanov Mikhail;pittore\nYolkina Ella;gruista\nIvanov Andrei;meccanico\nIvanova Alla;avvocato<\/code><\/pre>\n<p><\/p>\n<p>Evviva! Ce l'abbiamo fatta!<\/p>\n<p><\/p>\n<h1 id=\"rabota-nad-oshibkami\">Lavoro di correzione degli errori<\/h1>\n<p><\/p>\n<p>Ho gi\u00e0 risposto alle domande sulla ordinazione delle stringhe, sollevate all'inizio, ma ci sono ancora un paio di domande sugli errori \u2014 visibili e invisibili.<\/p>\n<p><\/p>\n<p>Torniamo al compito iniziale.<\/p>\n<p><\/p>\n<p>E il programma <em>sort<\/em> e il programma <em>join<\/em> utilizza le stesse funzioni di confronto delle stringhe di <em>glibc<\/em>. Com'\u00e8 possibile che <em>join<\/em> ha restituito un errore di ordinamento sulle stringhe ordinate dal comando <em>sort<\/em> nella locale <em>en_US.UTF-8<\/em>? \u041e\u0442\u0432\u0435\u0442 \u043f\u0440\u043e\u0441\u0442: <em>sort<\/em> confronta l'intera stringa, mentre <em>join<\/em> confronta solo la chiave, che di default \u00e8 l'inizio della stringa fino al primo carattere di spazio. Nel mio esempio, questo ha portato a un messaggio di errore poich\u00e9 l'ordinamento delle prime parole nelle stringhe non corrispondeva all'ordinamento delle stringhe complete.<\/p>\n<p><\/p>\n<p>Locale <em>&quot;C&quot;<\/em> garantisce che, nelle righe ordinate, le sottostringhe iniziali fino al primo spazio saranno anch'esse ordinate, ma questo maschera solo l'errore. \u00c8 possibile fornire dati (persone con lo stesso cognome ma nomi diversi) che, senza un messaggio di errore, potrebbero produrre un risultato errato durante la fusione dei file. Se vogliamo che <em>join<\/em> unifichi le righe dei file in base a nome e cognome, il modo corretto \u00e8 indicare esplicitamente il delimitatore dei campi e ordinare in base al campo chiave, e non all'intera riga. In questo caso, la fusione funzioner\u00e0 correttamente e non ci saranno errori in nessuna 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>Esempio eseguito con successo in codifica <em>CP1251<\/em> contiene un altro errore. Il fatto \u00e8 che in tutte le distribuzioni che conosco <em>Linux<\/em> mancano i pacchetti della locale compilata <em>ru_RU.CP1251<\/em>. Se la locale compilata non viene trovata, <em>sort<\/em> si utilizza silenziosamente il confronto byte a byte, come abbiamo Observato.<\/p>\n<p><\/p>\n<p>A proposito, c'\u00e8 un altro piccolo bug legato alla mancanza delle localit\u00e0 compilate. Il comando <em>LOCPATH=\/tmp locale -a<\/em> restituir\u00e0 un elenco di tutte le localit\u00e0 in <em>locale-archive<\/em>, ma con la variabile impostata <em>LOCPATH<\/em> per tutti i programmi (anche per il principale <em>locale<\/em>) queste localit\u00e0 non saranno disponibili.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; LOCPATH=\/tmp locale -a | grep en_US\nlocale: Impossibile impostare LC_CTYPE come locale predefinito: Nessun file o directory di questo tipo\nlocale: Impossibile impostare LC_MESSAGES come locale predefinito: Nessun file o directory di questo tipo\nlocale: Impossibile impostare LC_COLLATE come locale predefinito: Nessun file o directory di questo tipo\nen_US\nen_US.iso88591\nen_US.iso885915\nen_US.utf8\n\n$&gt; LC_COLLATE=en_US.UTF-8 sort --debug\nsort: utilizza le regole di ordinamento \u2018en_US.UTF-8\u2019\n\n$&gt; LOCPATH=\/tmp LC_COLLATE=en_US.UTF-8 sort --debug\nsort: utilizza un semplice confronto di byte<\/code><\/pre>\n<p><\/p>\n<h1 id=\"zaklyuchenie\">Conclusione<\/h1>\n<p><\/p>\n<p>Se sei un programmatore a cui piace pensare che le stringhe siano un insieme di byte, la tua scelta <em>LC_COLLATE=C<\/em>.<\/p>\n<p><\/p>\n<p>Se sei un linguista o un compilatore di dizionari, \u00e8 meglio che tu compili il tuo locale.<\/p>\n<p><\/p>\n<p>Se sei un utente semplice, \u00e8 sufficiente abituarsi al fatto che il comando <em>ls -a<\/em> restituisce file che iniziano con un punto, mescolati con file che iniziano con una lettera, e <em>Midnight Commander<\/em>, che usa le proprie funzioni interne per ordinare i nomi, porta i file che iniziano con un punto all'inizio dell'elenco.<\/p>\n<p><\/p>\n<h1 id=\"ssylki\">Link<\/h1>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/unicode.org\/reports\/tr10\/\">Rapporto n\u00b010 Algoritmo di ordinamento Unicode <\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"http:\/\/www.unicode.org\/Public\/UCA\/latest\/allkeys.txt\">Pesi dei caratteri su 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 implementazione della libreria per lavorare con Unicode di IBM. <\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"http:\/\/demo.icu-project.org\/icu-bin\/collation.html\">Test di ordinamento utilizzando <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\">Pesi dei caratteri in <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\">Descrizione del formato di file con pesi <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\">Discussione sul confronto delle stringhe in <em>glibc<\/em><\/a><\/noindex><\/p>\n<p>Fonte: <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 4.9.10 - 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 \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\" \/>\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\/it\/blog\/administrirovanie\/kak-linuxovskij-sort-sortiruet-stroki\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\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 \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\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/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\udd47Come il sort di Linux ordina le righe | ProHoster","description":"Introduzione Tutto \u00e8 iniziato con un breve script destinato a combinare informazioni sugli indirizzi e-mail dei dipendenti, ottenuti da un elenco di utenti di mailing list, con le posizioni dei dipendenti, prelevate dal database del personale. Entrambi gli elenchi sono stati esportati in file di testo in codifica Unicode UTF-8 e salvati con fine riga in formato Unix. Contenuto di mail.txt Ivanov Andrei;ia@example.com Contenuto di buhg.txt Ivanova Alla;pittore Yolkin","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/kak-linuxovskij-sort-sortiruet-stroki","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","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 \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","og:url":"https:\/\/prohoster.info\/it\/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"},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/83055","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=83055"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/83055\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=83055"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=83055"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=83055"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}