{"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\/es\/blog\/administrirovanie\/kak-linuxovskij-sort-sortiruet-stroki","title":{"rendered":"C\u00f3mo sort de Linux ordena cadenas","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<h1 id=\"vvedenie\">Introducci\u00f3n<\/h1>\n<p><\/p>\n<p>Todo comenz\u00f3 con un breve script que deb\u00eda combinar la informaci\u00f3n sobre las direcciones <em>correo electr\u00f3nico<\/em> de los empleados, obtenida de la lista de usuarios del bolet\u00edn, con los cargos de los empleados, obtenidos de la base de datos del departamento de Recursos Humanos. Ambas listas fueron exportadas a archivos de texto en codificaci\u00f3n Unicode <em>UTF-8<\/em> y se guardaron con finales de l\u00ednea de tipo Unix.<\/p>\n<p><\/p>\n<p>Contenido <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>Contenido <em>buhg.txt<\/em><\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Ivanova Alla;pintora\nYelkina Ella;gr\u00faa\nIvanov Andrey;cerrajero\nAbakanov Mikhail;pintor<\/code><\/pre>\n<p><\/p>\n<p>Para combinarlos, los archivos fueron ordenados con un comando de Unix <em>sort<\/em> y alimentados a un programa de Unix <em>join<\/em>, que finaliz\u00f3 inesperadamente con un error: <\/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: no est\u00e1 ordenado: Ivanov Andrey;cerrajero<\/code><\/pre>\n<p><\/p>\n<p>Una r\u00e1pida revisi\u00f3n del resultado de la ordenaci\u00f3n mostr\u00f3 que, en general, el ordenamiento era correcto, pero en caso de coincidencias de apellidos masculinos y femeninos, los femeninos iban antes que los masculinos:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; sort buhg.txt\nAbakanov Mikhail;pintor\nYelkina Ella;gr\u00faa\nIvanova Alla;pintora\nIvanov Andrey;cerrajero<\/code><\/pre>\n<p><\/p>\n<p>Parece un error de ordenaci\u00f3n en Unicode o una manifestaci\u00f3n del feminismo en el algoritmo de ordenaci\u00f3n. La primera opci\u00f3n es, por supuesto, m\u00e1s plausible.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Dejemos eso de lado por ahora <em>join<\/em> y centr\u00e9monos en <em>sort<\/em>. Intentemos resolver el problema mediante un enfoque de ensayo y error. Para comenzar, cambiaremos la configuraci\u00f3n regional de <em>en_US<\/em> en <em>ru_RU<\/em>. Para la ordenaci\u00f3n, habr\u00eda sido suficiente establecer la variable de entorno <em>LC_COLLATE<\/em>, pero no vamos a ser mezquinos:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; LANG=ru_RU.UTF-8 sort buhg.txt\nAbakanov Mikhail;pintor\nYelkina Ella;gr\u00faa\nIvanova Alla;pintora\nIvanov Andrey;cerrajero<\/code><\/pre>\n<p><\/p>\n<p>No ha cambiado nada.<\/p>\n<p><\/p>\n<p>Intentemos recodificar los archivos a una codificaci\u00f3n de un solo 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>Nuevamente, no ha cambiado nada.<\/p>\n<p><\/p>\n<p>No hay m\u00e1s remedio, tendr\u00e9 que buscar una soluci\u00f3n en internet. No hay nada directo sobre apellidos rusos, pero hay preguntas sobre otras rarezas en la ordenaci\u00f3n. Aqu\u00ed, por ejemplo, hay un problema as\u00ed: <noindex><a rel=\"nofollow\" href=\"https:\/\/serverfault.com\/questions\/95579\/unix-sort-treats-dash-characters-as-invisible\/95593\">unix sort trata los caracteres &#8216;-&#8216; (guion) como invisibles<\/a><\/noindex>. En resumen, las cadenas &quot;a-b&quot;, &quot;aa&quot;, &quot;ac&quot; se ordenan como &quot;aa&quot;, &quot;a-b&quot;, &quot;ac&quot;.<\/p>\n<p><\/p>\n<p>La respuesta en todas partes es la misma: use la configuraci\u00f3n regional de programador <em>&quot;C&quot;<\/em> y ser\u00e1n felices. Probemos:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; LANG=C sort buhg.txt\nYelkina Ella;gr\u00faa\nAbakanov Mikhail;pintor\nIvanov Andrey;cerrajero\nIvanova Alla;abogada<\/code><\/pre>\n<p><\/p>\n<p>Algo ha cambiado. Los Ivanov se han alineado en el orden correcto, aunque Yelkina se ha desviado. Volvamos al problema original:<\/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>Funcion\u00f3 sin errores, como prometi\u00f3 internet. Y eso a pesar de la primera l\u00ednea de Y\u00f3lkin.<\/p>\n<p><\/p>\n<p>Parece que el problema est\u00e1 resuelto, pero por si acaso probaremos con otra codificaci\u00f3n rusa: la de Windows. <em>CP1251<\/em>:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; iconv -f UTF-8 -t CP1251 buhg.txt \n | LANG=ru_RU.CP1251 sort \n | iconv -f CP1251 -t UTF8 <\/code><\/pre>\n<p><\/p>\n<p>El resultado de la ordenaci\u00f3n, curiosamente, coincidir\u00e1 con la localidad. <em>&quot;C&quot;<\/em>, y todo el ejemplo, por lo tanto, pasa sin errores. Es algo m\u00edstico.<\/p>\n<p><\/p>\n<p>No me gusta la m\u00edstica en la programaci\u00f3n, ya que, por lo general, oculta errores. Tendr\u00e9 que tomar en serio la cuesti\u00f3n de c\u00f3mo funciona <em>sort<\/em> y en qu\u00e9 afecta <em>LC_COLLATE<\/em> .<\/p>\n<p><\/p>\n<p>Al final intentar\u00e9 responder a las preguntas:<\/p>\n<p><\/p>\n<ul>\n<li>por qu\u00e9 los apellidos femeninos se ordenaron incorrectamente<\/li>\n<li>por la cual <em>LANG=ru_RU.CP1251<\/em> result\u00f3 ser equivalente <em>LANG=C<\/em><\/li>\n<li>por qu\u00e9 hay <em>sort<\/em> y <em>join<\/em> diferentes representaciones del orden de las cadenas ordenadas<\/li>\n<li>por qu\u00e9 en todos mis ejemplos hay errores<\/li>\n<li>finalmente, c\u00f3mo ordenar cadenas a mi gusto<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"sortirovka-v-yunikode\">Ordenaci\u00f3n en Unicode<\/h1>\n<p><\/p>\n<p>La primera parada ser\u00e1 el informe t\u00e9cnico n\u00famero 10 titulado <noindex><a rel=\"nofollow\" href=\"https:\/\/unicode.org\/reports\/tr10\/\">algoritmo de colaci\u00f3n Unicode<\/a><\/noindex> en el sitio web <noindex><a rel=\"nofollow\" href=\"https:\/\/unicode.org\">unicode.org<\/a><\/noindex>. El informe contiene muchos detalles t\u00e9cnicos, as\u00ed que me permitir\u00e9 presentar un resumen de las ideas principales.<\/p>\n<p><\/p>\n<p><em>Colaci\u00f3n<\/em> \u2014 &quot;comparaci\u00f3n&quot; de cadenas \u2014 es la base de cualquier algoritmo de ordenaci\u00f3n. Los propios algoritmos pueden diferir (&quot;burbuja&quot;, &quot;mezcla&quot;, &quot;r\u00e1pido&quot;), pero todos ellos utilizar\u00e1n la comparaci\u00f3n de pares de cadenas para determinar el orden en que deben aparecer.<\/p>\n<p><\/p>\n<p>La ordenaci\u00f3n de cadenas en lenguaje natural es un problema bastante complicado. Incluso en las m\u00e1s simples codificaciones de un solo byte, el orden de las letras en un alfabeto que difiere de la latina inglesa no coincidir\u00e1 con el orden de los valores num\u00e9ricos que codifican esas letras. As\u00ed, en el alfabeto alem\u00e1n, la letra <em>\u00d6<\/em> se encuentra entre <em>A<\/em> y <em>P<\/em>, y en la codificaci\u00f3n <em>CP850<\/em> se sit\u00faa entre <em>\u00ff<\/em> y <em>\u00dc<\/em>.<\/p>\n<p><\/p>\n<p>Se puede intentar abstraerse de la codificaci\u00f3n espec\u00edfica y considerar las &quot;letras ideales&quot;, que est\u00e1n dispuestas en un cierto orden, como se hace en Unicode. Codificaciones <em>UTF8<\/em>, <em>UTF16<\/em> o la de un solo byte <em>KOI8-R<\/em> (si se necesita un subconjunto limitado de Unicode) proporcionar\u00e1n diferentes representaciones num\u00e9ricas de las letras, pero referenciar\u00e1n los mismos elementos de la tabla base. <\/p>\n<p><\/p>\n<p>Resulta que incluso al construir una tabla de caracteres desde cero, no podremos asignar un orden universal de los caracteres en ella. En diferentes alfabetos nacionales que utilizan las mismas letras, el orden de estas letras puede variar. Por ejemplo, en el idioma franc\u00e9s <em>\u00c6<\/em> se considerar\u00e1 una ligadura y se ordenar\u00e1 como una cadena. <em>EA<\/em>En cambio, en el idioma noruego <em>\u00c6<\/em> se considerar\u00e1 como una letra separada, que se sit\u00faa despu\u00e9s de <em>Z<\/em>. Por cierto, adem\u00e1s de ligaduras como <em>\u00c6<\/em> hay letras que se escriben con varios s\u00edmbolos. As\u00ed, en el alfabeto checo hay una letra <em>Ch<\/em>, que se encuentra entre <em>H<\/em> y <em>I<\/em>.<\/p>\n<p><\/p>\n<p>Adem\u00e1s de las diferencias en los alfabetos, existen otras tradiciones nacionales que influyen en la ordenaci\u00f3n. En particular, surge la pregunta: \u00bfen qu\u00e9 orden deben seguir en el diccionario las palabras que consisten en letras may\u00fasculas y min\u00fasculas? Tambi\u00e9n las peculiaridades del uso de signos de puntuaci\u00f3n pueden influir en la ordenaci\u00f3n. En espa\u00f1ol, al inicio de una pregunta, se coloca un signo de interrogaci\u00f3n invertido (<em>\u00bfTe gusta la m\u00fasica?<\/em>). En este caso, est\u00e1 claro que las preguntas no deben agruparse en un cl\u00faster separado fuera del alfabeto, pero \u00bfc\u00f3mo se deben ordenar las cadenas con otros signos de puntuaci\u00f3n?<\/p>\n<p><\/p>\n<p>No me detendr\u00e9 en la ordenaci\u00f3n de cadenas en lenguas que se diferencian significativamente de las europeas. Cabe se\u00f1alar que en lenguas con direcci\u00f3n de escritura de derecha a izquierda o de arriba hacia abajo, los s\u00edmbolos en las cadenas probablemente se almacenan en el orden de lectura, y incluso en escrituras no alfab\u00e9ticas hay formas de ordenar las cadenas car\u00e1cter por car\u00e1cter. Por ejemplo, los caracteres pueden ordenarse por la forma (<noindex><a rel=\"nofollow\" href=\"https:\/\/studychinese.ru\/kljuchi\/\">claves de los caracteres chinos<\/a><\/noindex>) o por pronunciaci\u00f3n. La forma en que se deben ordenar los emojis, francamente, no lo s\u00e9, pero tambi\u00e9n se puede idear algo para ellos.<\/p>\n<p><\/p>\n<p>Sobre la base de las caracter\u00edsticas mencionadas anteriormente, se formularon los requisitos b\u00e1sicos para la comparaci\u00f3n de cadenas basadas en tablas Unicode:<\/p>\n<p><\/p>\n<ul>\n<li>la comparaci\u00f3n de cadenas no depende de la posici\u00f3n de los s\u00edmbolos en la tabla de c\u00f3digos;<\/li>\n<li>las secuencias de s\u00edmbolos que forman un \u00fanico s\u00edmbolo se llevan a su forma can\u00f3nica (<em>A<\/em> + el c\u00edrculo superior es lo mismo que <em>\u00c5<\/em>);<\/li>\n<li>) al comparar cadenas, el s\u00edmbolo se considera en el contexto de la cadena y, si es necesario, se combina con los vecinos en una \u00fanica unidad de comparaci\u00f3n (<em>Ch<\/em> en checo) o se divide en varias (<em>\u00c6<\/em> en franc\u00e9s);<\/li>\n<li>todas las caracter\u00edsticas nacionales (alfabeto, letras may\u00fasculas\/min\u00fasculas, signos de puntuaci\u00f3n, orden de las formas de escritura) deben configurarse hasta la asignaci\u00f3n manual del orden (emojis);<\/li>\n<li>la comparaci\u00f3n es importante no solo para la clasificaci\u00f3n, sino tambi\u00e9n en muchos otros lugares, como para establecer rangos de filas (sustituci\u00f3n {A\u2026 j} en <em>bash<\/em>);<\/li>\n<li>la comparaci\u00f3n debe realizarse lo suficientemente r\u00e1pido.<\/li>\n<\/ul>\n<p><\/p>\n<p>Adem\u00e1s, los autores del informe formularon las propiedades de comparaci\u00f3n en las que los desarrolladores de algoritmos no deben confiar:<\/p>\n<p><\/p>\n<ul>\n<li>el algoritmo de comparaci\u00f3n no debe requerir un conjunto separado de s\u00edmbolos para cada idioma (el ruso y el ucraniano comparten la mayor\u00eda de los s\u00edmbolos cir\u00edlicos);<\/li>\n<li>la comparaci\u00f3n no debe basarse en el orden de los caracteres en las tablas Unicode;<\/li>\n<li>el peso de la cadena no deber\u00eda ser un atributo de la cadena, ya que la misma cadena en diferentes contextos culturales puede tener diferentes pesos;<\/li>\n<li>los pesos de las cadenas pueden cambiar al fusionarse o dividirse (de <em>x<\/em> &lt; <em>y<\/em> no se debe interpretar que <em>xz<\/em> &lt; <em>yz<\/em>);<\/li>\n<li>diferentes cadenas que tienen el mismo peso se consideran iguales desde el punto de vista del algoritmo de clasificaci\u00f3n. Introducir un orden adicional para tales cadenas es posible, pero puede degradar el rendimiento;<\/li>\n<li>en las ordenaciones repetidas, las cadenas con el mismo peso pueden intercambiarse. La estabilidad es una propiedad de un algoritmo de clasificaci\u00f3n espec\u00edfico, no de un algoritmo de comparaci\u00f3n de cadenas (ver el punto anterior);<\/li>\n<li>las reglas de clasificaci\u00f3n pueden cambiar con el tiempo a medida que se precisan\/cambian las tradiciones culturales.<\/li>\n<\/ul>\n<p><\/p>\n<p>Tambi\u00e9n se establece que el algoritmo de comparaci\u00f3n no sabe nada sobre la sem\u00e1ntica de las cadenas procesadas. As\u00ed, las cadenas que consisten solo en d\u00edgitos no deben compararse como n\u00fameros, y en listas de nombres en ingl\u00e9s no debe eliminarse el art\u00edculo (<em>Beatles, The<\/em>).<\/p>\n<p><\/p>\n<p>Para satisfacer todos los requisitos mencionados, se propone un algoritmo de clasificaci\u00f3n tabular multilevel (de hecho, de cuatro niveles).<\/p>\n<p><\/p>\n<p>Previamente, los caracteres de la cadena se normalizan y se agrupan en unidades de comparaci\u00f3n. A cada unidad de comparaci\u00f3n se le asignan varios pesos, correspondientes a varios niveles de comparaci\u00f3n. Los pesos de las unidades de comparaci\u00f3n son elementos de conjuntos ordenados (en este caso, n\u00fameros enteros) que se pueden comparar por mayor o menor. Un valor especial <em>IGNORED<\/em> (0x0) significa que en el nivel de comparaci\u00f3n correspondiente, esta unidad no participa en la comparaci\u00f3n. La comparaci\u00f3n de cadenas puede repetirse varias veces, utilizando los pesos de los niveles correspondientes. En cada uno de los niveles, los pesos de las unidades de comparaci\u00f3n de dos cadenas se comparan entre s\u00ed de manera secuencial.<\/p>\n<p><\/p>\n<p>En diversas implementaciones del algoritmo para diferentes tradiciones nacionales, los valores de los coeficientes pueden diferir, pero el est\u00e1ndar Unicode incluye una tabla b\u00e1sica de pesos \u2014 <em>&quot;Default Unicode Collation Element Table&quot;<\/em> (<em>DUCET<\/em>). Quiero destacar que establecer una variable <em>LC_COLLATE<\/em> es, de hecho, una indicaci\u00f3n para elegir la tabla de pesos en la funci\u00f3n de comparaci\u00f3n de cadenas.<\/p>\n<p><\/p>\n<p>Los coeficientes de peso <em>DUCET<\/em> est\u00e1n estructurados de la siguiente manera:<\/p>\n<p><\/p>\n<ul>\n<li>en el primer nivel, todas las letras se convierten a una misma may\u00fascula, los signos diacr\u00edticos son desechados, y los signos de puntuaci\u00f3n (no todos) son ignorados;<\/li>\n<li>en el segundo nivel, solo se tienen en cuenta los signos diacr\u00edticos;<\/li>\n<li>en el tercer nivel, solo se toma en cuenta la may\u00fascula;<\/li>\n<li>en el cuarto nivel, solo se consideran los signos de puntuaci\u00f3n.<\/li>\n<\/ul>\n<p><\/p>\n<p>La comparaci\u00f3n se lleva a cabo en varias pasadas: primero se comparan los coeficientes del primer nivel; si los pesos coinciden, se realiza una comparaci\u00f3n repetida con los pesos del segundo nivel; luego, posiblemente, el tercero y el cuarto.<\/p>\n<p><\/p>\n<p>La comparaci\u00f3n se termina cuando en las cadenas hay unidades de comparaci\u00f3n correspondientes entre s\u00ed con diferentes pesos. Las cadenas que tienen pesos iguales en los cuatro niveles se consideran iguales entre s\u00ed.<\/p>\n<p><\/p>\n<p>Este algoritmo (con un mont\u00f3n de detalles t\u00e9cnicos adicionales) le dio nombre al informe n\u00ba 10 \u2014 <em>&quot;Unicode Collation Algorithm&quot;<\/em> (<em>UCA<\/em>).<\/p>\n<p><\/p>\n<p>Aqu\u00ed el comportamiento de ordenaci\u00f3n de nuestro ejemplo se vuelve un poco m\u00e1s comprensible. Ser\u00eda bueno compararlo con el est\u00e1ndar Unicode.<\/p>\n<p><\/p>\n<p>Para probar implementaciones <em>UCA<\/em> existe un <noindex><a rel=\"nofollow\" href=\"https:\/\/www.unicode.org\/Public\/UCA\/latest\/CollationTest.html\">test<\/a><\/noindex>, que utiliza <noindex><a rel=\"nofollow\" href=\"http:\/\/www.unicode.org\/Public\/UCA\/latest\/allkeys.txt\">un archivo de pesos<\/a><\/noindex>, que implementa <em>DUCET<\/em>. En el archivo de pesos se pueden encontrar diversas curiosidades. Por ejemplo, hay un orden de fichas de mahjong y domin\u00f3 europeo, as\u00ed como el orden de los palos en una baraja de cartas (s\u00edmbolo <em>1F000<\/em> y as\u00ed sucesivamente). Los palos de carta est\u00e1n organizados seg\u00fan las reglas del bridge \u2014 PCHBT, y las cartas en cada palo \u2014 en secuencia de 2,3\u2026 K.<\/p>\n<p><\/p>\n<p>Verificar manualmente la correcta ordenaci\u00f3n de cadenas de acuerdo con <em>DUCET<\/em> ser\u00eda bastante tediosa, pero, afortunadamente para nosotros, existe una implementaci\u00f3n ejemplar de una biblioteca para trabajar con Unicode \u2014 &quot;<noindex><a rel=\"nofollow\" href=\"http:\/\/site.icu-project.org\/\">Componentes Internacionales para Unicode<\/a><\/noindex>&quot; (<em>ICU<\/em>).<\/p>\n<p><\/p>\n<p>En el sitio de esta biblioteca, desarrollada en <em>IBM<\/em>, hay p\u00e1ginas de demostraci\u00f3n, incluyendo <noindex><a rel=\"nofollow\" href=\"http:\/\/demo.icu-project.org\/icu-bin\/collation.html\">la p\u00e1gina del algoritmo de comparaci\u00f3n de cadenas<\/a><\/noindex>. Introducimos nuestras cadenas de prueba con la configuraci\u00f3n predeterminada y, \u00a1oh maravilla!, obtenemos una clasificaci\u00f3n rusa perfecta.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Abakanov Mikhail; pintor\nYolkina Ella; gr\u00faa\nIvanov Andrey; cerrajero\nIvanova Alla; abogada<\/code><\/pre>\n<p><\/p>\n<p>Por cierto, en el sitio <em>ICU<\/em> se puede encontrar una aclaraci\u00f3n sobre c\u00f3mo funciona el algoritmo de comparaci\u00f3n al procesar signos de puntuaci\u00f3n. En los ejemplos <noindex><a rel=\"nofollow\" href=\"http:\/\/userguide.icu-project.org\/collation\/faq\">Preguntas frecuentes sobre la clasificaci\u00f3n<\/a><\/noindex> se ignoran el ap\u00f3strofo y el guion.<\/p>\n<p><\/p>\n<p>Unicode nos ayud\u00f3, pero tendremos que buscar las razones del comportamiento extra\u00f1o <em>sort<\/em> en <em>Linux<\/em> en alg\u00fan otro lugar.<\/p>\n<p><\/p>\n<h1 id=\"sortirovka-v-glibc\">Clasificaci\u00f3n en glibc<\/h1>\n<p><\/p>\n<p>Una r\u00e1pida revisi\u00f3n del c\u00f3digo fuente de la utilidad <em>sort<\/em> de <em>GNU Core Utils<\/em> mostr\u00f3 que en la propia utilidad, la localizaci\u00f3n se reduce a imprimir el valor actual de la variable <em>LC_COLLATE<\/em> al ejecutarse en modo de depuraci\u00f3n:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$ sort --debug buhg.txt &gt; buhg.srt\nsort: utilizando las reglas de clasificaci\u00f3n \u2018en_US.UTF8\u2019<\/code><\/pre>\n<p><\/p>\n<p>La comparaci\u00f3n de cadenas se realiza mediante la funci\u00f3n est\u00e1ndar <em>strcoll<\/em>, lo que significa que todo lo interesante se encuentra en la biblioteca <em>glibc<\/em>.<\/p>\n<p><\/p>\n<p>En <em>wiki<\/em> el proyecto <em>glibc<\/em> la comparaci\u00f3n de cadenas est\u00e1 dedicada a <noindex><a rel=\"nofollow\" href=\"https:\/\/sourceware.org\/glibc\/wiki\/Locales#LC_COLLATE\">un p\u00e1rrafo<\/a><\/noindex>. De este p\u00e1rrafo se puede entender que en <em>glibc<\/em> la clasificaci\u00f3n se basa en el algoritmo que ya conocemos <em>UCA<\/em> (<em>El algoritmo de clasificaci\u00f3n Unicode<\/em>) y\/o en un est\u00e1ndar cercano a \u00e9l <em>ISO 14651<\/em> (<em>Ordenaci\u00f3n y comparaci\u00f3n de cadenas internacionales<\/em>). Con respecto a este \u00faltimo est\u00e1ndar, se debe notar que en el sitio <noindex><a rel=\"nofollow\" href=\"https:\/\/standards.iso.org\/ittf\/PubliclyAvailableStandards\">standards.iso.org<\/a><\/noindex> <em>ISO 14651<\/em> se declara oficialmente p\u00fablico, pero el enlace correspondiente lleva a una p\u00e1gina inexistente. Google devuelve varias p\u00e1ginas con enlaces a sitios oficiales que ofrecen comprar una copia electr\u00f3nica del est\u00e1ndar por un centenar de euros, pero en la tercera o cuarta p\u00e1gina de los resultados de b\u00fasqueda se pueden encontrar enlaces directos a <em>PDF<\/em>. En general, el est\u00e1ndar no se diferencia pr\u00e1cticamente de <em>UCA<\/em>, pero se lee con m\u00e1s aburrimiento, ya que no contiene ejemplos v\u00edvidos de las peculiaridades nacionales en la clasificaci\u00f3n de cadenas. <\/p>\n<p><\/p>\n<p>La informaci\u00f3n m\u00e1s interesante en <em>wiki<\/em> result\u00f3 ser un enlace a <noindex><a rel=\"nofollow\" href=\"https:\/\/sourceware.org\/bugzilla\/show_bug.cgi?id=14095\">un rastreador de errores<\/a><\/noindex> con una discusi\u00f3n sobre la implementaci\u00f3n de la comparaci\u00f3n de cadenas en <em>glibc<\/em>. De la discusi\u00f3n se puede saber que en <em>glibc<\/em> para la comparaci\u00f3n de cadenas se utiliza <em>ISO<\/em>una tabla <noindex><a rel=\"nofollow\" href=\"http:\/\/www.iso.org\/ittf\/ISO14651_2006_TABLE1_en.txt\">The Common Template Table<\/a><\/noindex> (<em>CTT<\/em>), cuya direcci\u00f3n se puede encontrar en el ap\u00e9ndice <em>A<\/em> del est\u00e1ndar <em>ISO 14651<\/em>. Entre 2000 y 2015, esta tabla en <em>glibc<\/em> no ten\u00eda un mantenedor y se diferenciaba notablemente (al menos en apariencia) de la versi\u00f3n actual del est\u00e1ndar. Desde 2015 hasta 2018, se llev\u00f3 a cabo la adaptaci\u00f3n a la nueva versi\u00f3n de la tabla y en este momento tienes la oportunidad de encontrar en la vida real tanto la nueva versi\u00f3n de la tabla (<em>CentOS 8<\/em>), como la antigua (<em>CentOS 7<\/em>). <\/p>\n<p><\/p>\n<p>Ahora que tenemos toda la informaci\u00f3n sobre el algoritmo y las tablas auxiliares, podemos volver al problema original y entender c\u00f3mo se deben ordenar correctamente las cadenas en una configuraci\u00f3n local rusa.<\/p>\n<p><\/p>\n<h1 id=\"iso-1465114652\">ISO 14651\/14652<\/h1>\n<p><\/p>\n<p>El c\u00f3digo fuente de la tabla que nos interesa <em>CTT<\/em> se encuentra en la mayor\u00eda de las distribuciones <em>Linux<\/em> en el directorio <em>\/usr\/share\/i18n\/locales\/<\/em>. La tabla en s\u00ed se encuentra en el archivo <em>iso14651_t1_common<\/em>. Luego, este archivo se incluye en el archivo <em>copy iso14651_t1_common<\/em> , que, a su vez, se incluye en los archivos nacionales, incluidos los de <em>. En la mayor\u00eda de las distribuciones<\/em>todos los archivos fuente est\u00e1n incluidos en la instalaci\u00f3n base, pero si no est\u00e1n, deber\u00e1s instalar un paquete adicional de la distribuci\u00f3n. <em>en_US<\/em> y <em>ru_RU<\/em>puede parecer horriblemente prolijo, con reglas poco claras para la construcci\u00f3n de nombres, pero si se analiza, es bastante simple. La estructura est\u00e1 descrita en el est\u00e1ndar <em>Linux<\/em> ISO 14652<\/p>\n<p><\/p>\n<p>Estructura del archivo <em>. En la mayor\u00eda de las distribuciones<\/em> , una copia del cual se puede descargar del sitio <em>open-std.org<\/em>. Otra descripci\u00f3n del formato del archivo se puede leer en <noindex><a rel=\"nofollow\" href=\"http:\/\/www.open-std.org\/JTC1\/SC22\/WG20\/docs\/n972-14652ft.pdf\">OpenGroup<\/a><\/noindex>. Como alternativa a leer el est\u00e1ndar, se pueden estudiar los textos fuente de la funci\u00f3n <noindex><a rel=\"nofollow\" href=\"https:\/\/pubs.opengroup.org\/onlinepubs\/9699919799\/basedefs\/V1_chap07.html\">las especificaciones<\/a><\/noindex> <em>POSIX<\/em> desde <em>collate_read<\/em>glibc\/locale\/programs\/ld-collate.c <em>La estructura del archivo es la siguiente:<\/em> en <em>Por defecto, el s\u00edmbolo se utiliza como car\u00e1cter de escape, y el final de l\u00ednea despu\u00e9s del s\u00edmbolo # es un comentario. Ambos s\u00edmbolos se pueden redefinir, lo que se ha hecho en la nueva versi\u00f3n de la tabla:<\/em>.<\/p>\n<p><\/p>\n<p>escape_char \/\ncomment_char %<\/p>\n<p><\/p>\n<p>En el archivo se encontrar\u00e1n tokens en formato<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">escape_char \/ comentario_char %<\/code><\/pre>\n<p><\/p>\n<p>En el archivo se encontrar\u00e1n tokens en formato <em>\u2014 un d\u00edgito hexadecimal). Esta representaci\u00f3n hexadecimal de los puntos de c\u00f3digo Unicode est\u00e1 en la codificaci\u00f3n<\/em> o <em>UCS-4<\/em> (donde <em>x<\/em> UTF-32 <em>). Todos los dem\u00e1s elementos en \u00e1ngulos (incluidos<\/em> (<em>UTF-32<\/em>). Todos los dem\u00e1s elementos entre corchetes angulares (incluyendo <em>y similares), se consideran constantes de cadena simples, sin sentido fuera de contexto.<\/em>, <em>nos dice que a continuaci\u00f3n empiezan los datos que describen la comparaci\u00f3n de cadenas.<\/em> Primero se definen nombres para los pesos en la tabla de comparaci\u00f3n y nombres para combinaciones de caracteres. En general, dos tipos de nombres pertenecen a dos entidades diferentes, pero en el archivo real est\u00e1n mezclados. Los nombres de los pesos se definen con la palabra clave<\/p>\n<p><\/p>\n<p>Cadena <em>LC_COLLATE<\/em> collating-symbol<\/p>\n<p><\/p>\n<p>Primero se asignan nombres para los pesos en la tabla de comparaci\u00f3n y nombres para las combinaciones de caracteres. En general, dos tipos de nombres pertenecen a dos entidades diferentes, pero en el archivo real est\u00e1n mezclados. Los nombres de los pesos se definen con la palabra clave <em>collating-symbol<\/em> (s\u00edmbolo de comparaci\u00f3n), ya que al comparar los caracteres Unicode con pesos iguales, se considerar\u00e1n s\u00edmbolos equivalentes.<\/p>\n<p><\/p>\n<p>La longitud total de la secci\u00f3n en la revisi\u00f3n actual del archivo es de aproximadamente 900 l\u00edneas. He extra\u00eddo ejemplos de varios lugares para mostrar la arbitrariedad de los nombres y varios tipos de sintaxis.<\/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; % Valor del s\u00edmbolo garantizado m\u00e1s grande. Mantener al final de esta lista\n...\ncollating-element &lt;U0413_0301&gt; from &quot;&lt;U0413&gt;&lt;U0301&gt;&quot;\ncollating-element &lt;U0413_0341&gt; from &quot;&lt;U0413&gt;&lt;U0341&gt;&quot;<\/code><\/pre>\n<p><\/p>\n<ul>\n<li><em>collating-symbol<\/em> registra la cadena <em>OSMANYA<\/em> en la tabla de nombres de pesos <\/li>\n<li><em>collating-symbol ..<\/em> registra una secuencia de nombres compuesta por un prefijo <em>S<\/em> y un sufijo num\u00e9rico hexadecimal de <em>1D000<\/em> hasta <em>1D35F<\/em>.<\/li>\n<li><em>FFFF<\/em> en <em>collating-symbol<\/em> se ve como un n\u00famero entero sin signo grande en el sistema hexadecimal, pero <em>&lt;SFFFF&gt;<\/em> es solo un nombre que podr\u00eda verse como <em>&lt;VERYBIGVAL&gt;<\/em> <\/li>\n<li>nombre <em>&lt;U0413&gt;<\/em> significa el punto de c\u00f3digo en la codificaci\u00f3n <em>). Todos los dem\u00e1s elementos en \u00e1ngulos (incluidos<\/em><\/li>\n<li><em>collating-element &lt;U0413_0301&gt; from &quot;&lt;U0413&gt;&lt;U0301&gt;&quot;<\/em> registra un nuevo nombre para un par de puntos Unicode. <\/li>\n<\/ul>\n<p><\/p>\n<p>Cuando se definen los nombres de los pesos, se establecen los pesos propiamente dichos. Dado que al comparar solo importa la relaci\u00f3n mayor-menor, los pesos se definen en una simple secuencia de enumeraci\u00f3n de nombres. Primero se enumeran los pesos &quot;ligeros&quot;, luego los pesos &quot;pesados&quot;. Recuerdo que a cada s\u00edmbolo de Unicode se le asigna cuatro pesos diferentes. Aqu\u00ed se condensan en una secuencia ordenada \u00fanica. Te\u00f3ricamente, cualquier nombre simb\u00f3lico puede usarse en cualquiera de los cuatro niveles, pero los comentarios indican que los desarrolladores mentalmente clasifican los nombres por niveles.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">% Asignaciones de peso simb\u00f3lico\n\n% Asignaciones de peso de tercer nivel\n\n\n\n\n...\n% Asignaciones de peso de segundo nivel\n\n % COMBINANDO LINEA BAJA\n % COMBINANDO COMA ARRIBA\n % COMBINANDO COMA INVERSO ARRIBA\n...\n% Asignaciones de peso de primer nivel\n % TABULACI\u00d3N HORIZONTAL \n % SALTO DE L\u00cdNEA\n % TABULACI\u00d3N VERTICAL\n...\n % LETRA PEQUE\u00d1A CYR\u00cdLICA DE\n % LETRA PEQUE\u00d1A CYR\u00cdLICA DE KOMI\n % LETRA PEQUE\u00d1A CYR\u00cdLICA DJE\n % LETRA PEQUE\u00d1A CYR\u00cdLICA DJE DE KOMI\n % LETRA PEQUE\u00d1A CYR\u00cdLICA GJE\n % LETRA PEQUE\u00d1A CYR\u00cdLICA ZE CON DESCENSOR\n % LETRA PEQUE\u00d1A CYR\u00cdLICA IE\n % LETRA PEQUE\u00d1A CYR\u00cdLICA IE CON BREVE\n % LETRA PEQUE\u00d1A CYR\u00cdLICA UKRAINIAN IE\n % LETRA PEQUE\u00d1A CYR\u00cdLICA ZHE<\/code><\/pre>\n<p><\/p>\n<p>Finalmente, la tabla de pesos en s\u00ed.<\/p>\n<p><\/p>\n<p>La secci\u00f3n de pesos est\u00e1 encerrada en filas con palabras clave <em>order_start<\/em> y <em>order_end<\/em>. Par\u00e1metros adicionales <em>order_start<\/em> definen en qu\u00e9 direcci\u00f3n se visualizan las filas en cada nivel de comparaci\u00f3n. Por defecto se utiliza el par\u00e1metro <em>forward<\/em>. El cuerpo de la secci\u00f3n consiste en filas que contienen el c\u00f3digo de car\u00e1cter y sus cuatro pesos. El c\u00f3digo de car\u00e1cter puede ser representado por el propio s\u00edmbolo, el punto de c\u00f3digo o un nombre simb\u00f3lico definido anteriormente. Los pesos tambi\u00e9n pueden estar dados por nombres simb\u00f3licos, puntos de c\u00f3digo o los propios s\u00edmbolos. Si se utilizan puntos de c\u00f3digo o s\u00edmbolos, su peso coincide con el valor num\u00e9rico del punto de c\u00f3digo (posici\u00f3n en la tabla Unicode). Los s\u00edmbolos no especificados expl\u00edcitamente (seg\u00fan entiendo) se consideran a\u00f1adidos a la tabla con un peso primario que coincide con la posici\u00f3n en la tabla Unicode. El valor especial del peso <em>IGNORE<\/em> significa que en el nivel de comparaci\u00f3n correspondiente, este s\u00edmbolo es ignorado.<\/p>\n<p><\/p>\n<p>Para demostrar la estructura de pesos, eleg\u00ed tres fragmentos bastante obvios:<\/p>\n<p><\/p>\n<ul>\n<li>s\u00edmbolos que se ignoran por completo<\/li>\n<li>s\u00edmbolos equivalentes al n\u00famero tres en los dos primeros niveles<\/li>\n<li>el comienzo del alfabeto cir\u00edlico, que no contiene diacr\u00edticos y, por lo tanto, se ordena principalmente por los primeros y terceros niveles.<\/li>\n<\/ul>\n<p><\/p>\n<pre><code class=\"plaintext\">order_start forward;forward;forward;forward,position\n IGNORE;IGNORE;IGNORE;IGNORE % NULL (en 6429)\n IGNORE;IGNORE;IGNORE;IGNORE % INICIO DE CABECERA (en 6429)\n IGNORE;IGNORE;IGNORE;IGNORE % INICIO DE TEXTO (en 6429)\n...\n ;;; % DIGITO TRES\n ;;; % DIGITO TRES DE ANCHO COMPLETO\n ;;; % DIGITO TRES ENTRE PAR\u00c9NTESIS\n ;;; % DIGITO TRES PUNTO FINAL\n ;;<FONT>; % DIGITO TRES EN NEGRITA MATEM\u00c1TICA\n...\n ;;; % LETRA CIR\u00cdLICA PEQUE\u00d1A A\n ;;; % LETRA CIR\u00cdLICA MAY\u00daSCULA A\n ;;; % LETRA CIR\u00cdLICA PEQUE\u00d1A A CON BREVE\n ;;; % LETRA CIR\u00cdLICA PEQUE\u00d1A A CON BREVE\n...\n ;;; % LETRA CIR\u00cdLICA PEQUE\u00d1A BE\n ;;; % LETRA CIR\u00cdLICA MAY\u00daSCULA BE\n ;;; % LETRA CIR\u00cdLICA PEQUE\u00d1A VE\n ;;; % LETRA CIR\u00cdLICA MAY\u00daSCULA VE\n...\norder_end<\/code><\/pre>\n<p><\/p>\n<p>Ahora podemos volver a la clasificaci\u00f3n de ejemplos del principio del art\u00edculo. La trampa est\u00e1 en esta parte de la tabla de pesos:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">IGNORE;IGNORE;IGNORE; % ESPACIO\n IGNORE;IGNORE;IGNORE; % SIGNO DE EXCLAMACI\u00d3N\n IGNORE;IGNORE;IGNORE; % COMILLAS\n...<\/code><\/pre>\n<p><\/p>\n<p>Es evidente que en esta tabla los signos de puntuaci\u00f3n provienen de la tabla. <em>ASCII<\/em> (incluido el espacio) se ignora pr\u00e1cticamente siempre al comparar cadenas. Las \u00fanicas excepciones son las cadenas que coinciden en todo, excepto por los signos de puntuaci\u00f3n que se encuentran en posiciones coincidentes. Las cadenas de mi ejemplo (despu\u00e9s de la clasificaci\u00f3n) para el algoritmo de comparaci\u00f3n se ven as\u00ed:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">AbakanovMikhailpintor\nYolkinaEllacartista\nIvanovaAllamalpintor\nIvanovAndreycarpintero<\/code><\/pre>\n<p><\/p>\n<p>Teniendo en cuenta que en la tabla de pesos las letras may\u00fasculas en el idioma ruso vienen despu\u00e9s de las min\u00fasculas (en el tercer nivel <em>&lt;CAP&gt;<\/em> m\u00e1s pesado que <em>&lt;MIN&gt;<\/em>), la clasificaci\u00f3n parece absolutamente correcta.<\/p>\n<p><\/p>\n<p>Al establecer la variable <em>LC_COLLATE=C<\/em> se carga una tabla especial que define la comparaci\u00f3n byte a byte.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">static const uint32_t collseqwc[] =\n{\n  8, 1, 8, 0x0, 0xff,\n    * tabla de primer nivel *\n  6 * sizeof (uint32_t),\n    * tabla de segundo nivel *\n  7 * sizeof (uint32_t),\n    * tabla de tercer 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>Dado que en Unicode el punto de c\u00f3digo \u0401, est\u00e1 antes de \u0410, las cadenas se clasifican de manera correspondiente.<\/p>\n<p><\/p>\n<h1 id=\"tekstovye-i-dvoichnye-tablicy\">Tablas textuales y binarias<\/h1>\n<p><\/p>\n<p>Es obvio que la comparaci\u00f3n de cadenas es una operaci\u00f3n extremadamente frecuente, mientras que el an\u00e1lisis de la tabla <em>CTT<\/em> es un procedimiento bastante costoso. Para optimizar el acceso a la tabla, se compila en forma binaria mediante el comando <em>localedef<\/em>.<\/p>\n<p><\/p>\n<p>Comando <em>localedef<\/em> acepta como par\u00e1metros un archivo con la tabla de caracter\u00edsticas nacionales (opci\u00f3n <em>, el intervalo entre el env\u00edo de paquetes.<\/em>), en la que todos los s\u00edmbolos est\u00e1n representados por puntos de Unicode, y un archivo de correspondencia de puntos de Unicode con caracteres de una codificaci\u00f3n espec\u00edfica (opci\u00f3n <em>-f<\/em>). Como resultado del trabajo, se crean archivos binarios para la localidad, con el nombre indicado en el \u00faltimo par\u00e1metro.<\/p>\n<p><\/p>\n<p><em>Glibc<\/em> admite dos formatos de archivos binarios: &quot;tradicional&quot; y &quot;moderno&quot;.<\/p>\n<p><\/p>\n<p>El formato tradicional implica que el nombre de la localidad es el nombre de un subdirectorio en <em>\/usr\/lib\/locale\/<\/em>. En este subdirectorio se almacenan los archivos binarios <em>LC_COLLATE<\/em>, <em>LC_CTYPE<\/em>, <em>LC_TIME<\/em> etc. El archivo <em>LC_IDENTIFICATION<\/em> contiene el nombre formal de la localidad (que puede diferir del nombre del directorio) y comentarios.<\/p>\n<p><\/p>\n<p>El formato moderno supone el almacenamiento de todas las localidades en un \u00fanico archivo comprimido <em>\/usr\/lib\/locale\/locale-archive<\/em>, que se mapea en la memoria virtual de todos los procesos que lo utilizan. <em>glibc<\/em>El nombre de la configuraci\u00f3n regional en formato moderno se somete a cierta canonizaci\u00f3n: en los nombres de la codificaci\u00f3n permanecen solo los n\u00fameros y letras, convertidos a min\u00fasculas. As\u00ed <em>es_ES.UTF-8<\/em>, se guardar\u00e1 como <em>es_ES.utf-8<\/em>.<\/p>\n<p><\/p>\n<p>Los archivos de entrada se buscan en el directorio actual, as\u00ed como en los directorios <em>\/usr\/share\/i18n\/locales\/<\/em> y <em>\/usr\/share\/i18n\/charmaps\/<\/em> para archivos <em>CTT<\/em> y archivos de codificaci\u00f3n respectivamente.<\/p>\n<p><\/p>\n<p>Por ejemplo, el comando<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">localedef -i es_ES -f UTF-8 es_ES.UTF-8<\/code><\/pre>\n<p><\/p>\n<p>compilar\u00e1 el archivo <em>\/usr\/share\/i18n\/locales\/ru_RU<\/em> usando el archivo de codificaci\u00f3n <em>\/usr\/share\/i18n\/charmaps\/MAC-CYRILLIC.gz<\/em> y guardar\u00e1 el resultado en <em>\/usr\/lib\/locale\/locale-archive<\/em> con el nombre <em>es_ES.utf8<\/em><\/p>\n<p><\/p>\n<p>Si se establece la variable <em>LANG=es_ES.UTF-8<\/em> entonces <em>glibc<\/em> buscar\u00e1 archivos binarios de la configuraci\u00f3n regional en la siguiente secuencia de archivos y directorios:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">\/usr\/lib\/locale\/locale-archive\n\/usr\/lib\/locale\/en_US.UTF-8\/\n\/usr\/lib\/locale\/en_US\/\n\/usr\/lib\/locale\/enUTF-8\/\n\/usr\/lib\/locale\/en\/<\/code><\/pre>\n<p><\/p>\n<p>Si la configuraci\u00f3n regional aparece tanto en formatos tradicionales como modernos, se da prioridad al moderno.<\/p>\n<p><\/p>\n<p>Se puede ver la lista de configuraciones regionales compiladas con el comando <em>locale -a<\/em>.<\/p>\n<p><\/p>\n<h1 id=\"podgotovka-svoey-tablicy-sravneniya\">Preparando su propia tabla de comparaci\u00f3n<\/h1>\n<p><\/p>\n<p>Ahora, armado con conocimientos, puede crear su propia tabla de comparaci\u00f3n ideal de cadenas. Esta tabla debe comparar correctamente las letras espa\u00f1olas, incluyendo la letra \u00d1, y tener en cuenta los signos de puntuaci\u00f3n de acuerdo con la tabla <em>ASCII<\/em>.<\/p>\n<p><\/p>\n<p>El proceso de preparaci\u00f3n de su propia tabla de ordenaci\u00f3n consta de dos etapas: la edici\u00f3n de la tabla de pesos y su compilaci\u00f3n en forma binaria con el comando <em>localedef<\/em>.<\/p>\n<p><\/p>\n<p>Para que la tabla de comparaci\u00f3n pueda ajustarse con un m\u00ednimo de esfuerzo de edici\u00f3n, en el formato <em>open-std.org<\/em> se prev\u00e9n secciones de ajuste de pesos de la tabla existente. La secci\u00f3n comienza con la palabra clave <em>reorder-after<\/em> y la indicaci\u00f3n de la posici\u00f3n despu\u00e9s de la cual se realiza el reemplazo. La secci\u00f3n se cierra con la l\u00ednea <em>reorder-end<\/em>. Si es necesario corregir varias partes de la tabla, se crea una secci\u00f3n para cada una de esas partes.<\/p>\n<p><\/p>\n<p>He copiado las nuevas versiones de los archivos <em>iso14651_t1_common<\/em> y <em>ru_RU<\/em> del repositorio <em>glibc<\/em> a mi directorio personal ~\/local\/share\/i18n\/locales\/ y he editado ligeramente la secci\u00f3n <em>LC_COLLATE<\/em> en <em>ru_RU<\/em>. Las nuevas versiones de los archivos son completamente compatibles con mi versi\u00f3n <em>glibc<\/em>. Si desea utilizar versiones anteriores de los archivos, tendr\u00e1 que cambiar los nombres simb\u00f3licos y la ubicaci\u00f3n desde donde comienza el reemplazo en la tabla.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">LC_COLLATE\n% Copiar la plantilla de ISO\/IEC 14651\ncopy &quot;iso14651_t1&quot;\nreorder-after &lt;U000D&gt;\n&lt;U0020&gt; &lt;S0020&gt;;&lt;BASE&gt;;&lt;MIN&gt;&lt;U0020&gt; % ESPACIO\n&lt;U0021&gt; &lt;S0021&gt;&lt;BASE&gt;&lt;MIN&gt;&lt;U0021&gt; % SIGNO DE EXCLAMACI\u00d3N\n&lt;U0022&gt; &lt;S0022&gt;&lt;BASE&gt;&lt;MIN&gt;&lt;U0022&gt; % COMILLAS\n...\n&lt;U007D&gt; &lt;S007D&gt;&lt;BASE&gt;&lt;MIN&gt;&lt;U007D&gt; % LLAVE CERRADA DERECHA\n&lt;U007E&gt; &lt;S007E&gt;&lt;BASE&gt;&lt;MIN&gt;&lt;U007E&gt; % TILDIE\nreorder-end\nEND LC_COLLATE<\/code><\/pre>\n<p><\/p>\n<p>De hecho, habr\u00eda que cambiar los campos en <em>LC_IDENTIFICATION<\/em> para que apunten a la localidad <em>ru_MY<\/em>, pero en mi ejemplo no fue necesario, ya que exclu\u00ed de la b\u00fasqueda la localidad del archivo <em>locale-archive<\/em>.<\/p>\n<p><\/p>\n<p>Para <em>localedef<\/em> trabaj\u00e9 con archivos en mi carpeta a trav\u00e9s de la variable <em>I18NPATH<\/em> se puede a\u00f1adir un directorio adicional para la b\u00fasqueda de archivos de entrada, y el directorio para guardar los archivos binarios se puede especificar como una ruta con barras:<\/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> supone que en <em>LANG<\/em> se pueden escribir rutas absolutas a los directorios con archivos locales que comienzan con una barra, pero <em>glibc<\/em> en <em>Linux<\/em> todas las rutas se consideran desde el directorio base, que se puede redefinir a trav\u00e9s de la variable <em>LOCPATH<\/em>. Despu\u00e9s de establecer <em>LOCPATH=~\/.local\/lib\/locale\/<\/em> todos los archivos relacionados con la localizaci\u00f3n se buscar\u00e1n solo en mi carpeta. El archivo de localidades con la variable establecida <em>LOCPATH<\/em> se ignora.<\/p>\n<p><\/p>\n<p>Aqu\u00ed est\u00e1 la prueba decisiva:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; LANG=ru_MY.UTF-8 LOCPATH=~\/.local\/lib\/locale\/ sort buhg.txt\nAbakanov Mikhail;pintor\nYolkina Ella;gr\u00faa\nIvanov Andrey;cerrajero\nIvanova Alla;abogada<\/code><\/pre>\n<p><\/p>\n<p>\u00a1Hurra! \u00a1Lo hemos logrado!<\/p>\n<p><\/p>\n<h1 id=\"rabota-nad-oshibkami\">Trabajando en corregir errores<\/h1>\n<p><\/p>\n<p>Ya he respondido a las preguntas sobre la ordenaci\u00f3n de cadenas planteadas al principio, pero a\u00fan quedan un par de preguntas sobre errores, visibles e invisibles.<\/p>\n<p><\/p>\n<p>Volvamos a la tarea original.<\/p>\n<p><\/p>\n<p>Y el programa <em>sort<\/em> y el programa <em>join<\/em> utilizan las mismas funciones de comparaci\u00f3n de cadenas de <em>glibc<\/em>. \u00bfC\u00f3mo es que <em>join<\/em> proporcion\u00f3 un error de ordenaci\u00f3n en las cadenas ordenadas por el comando <em>sort<\/em> en la localidad <em>en_US.UTF-8<\/em>? \u041e\u0442\u0432\u0435\u0442 \u043f\u0440\u043e\u0441\u0442: <em>sort<\/em> compara la cadena completa, mientras que <em>join<\/em> solo compara la clave, que por defecto es el inicio de la cadena hasta el primer car\u00e1cter de espacio. En mi ejemplo, esto llev\u00f3 a un mensaje de error porque la ordenaci\u00f3n de las primeras palabras en las cadenas no coincidi\u00f3 con la ordenaci\u00f3n de las cadenas completas.<\/p>\n<p><\/p>\n<p>La localidad <em>&quot;C&quot;<\/em> asegura que en las cadenas ordenadas las subcadenas iniciales hasta el primer espacio tambi\u00e9n est\u00e9n ordenadas, pero esto solo oculta el error. Se pueden elegir datos como (personas con el mismo apellido pero diferentes nombres) que sin un mensaje de error dar\u00edan un resultado incorrecto al fusionar archivos. Si queremos que <em>join<\/em> fusionar cadenas de archivos por nombre completo, el enfoque correcto ser\u00eda especificar expl\u00edcitamente el delimitador de campos y ordenar por el campo clave, no por toda la cadena. En este caso, tanto la fusi\u00f3n se realizar\u00e1 correctamente como no habr\u00e1 errores en ninguna localidad:<\/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>Ejemplo ejecutado con \u00e9xito en la codificaci\u00f3n <em>CP1251<\/em> contiene otro error. El problema es que en todas las distribuciones que conozco <em>Linux<\/em> los paquetes carecen de una localizaci\u00f3n compilada <em>ru_RU.CP1251<\/em>. Si no se encuentra la localizaci\u00f3n compilada, <em>sort<\/em> silenciosamente utiliza la comparaci\u00f3n byte a byte, que es lo que hemos observado.<\/p>\n<p><\/p>\n<p>Por cierto, hay un peque\u00f1o glitch relacionado con la falta de localizaciones compiladas. El comando <em>LOCPATH=\/tmp locale -a<\/em> listar\u00e1 todas las localizaciones en <em>locale-archive<\/em>, pero si la variable est\u00e1 establecida <em>LOCPATH<\/em> para todos los programas (incluida la misma <em>locale<\/em>) estas localizaciones no estar\u00e1n disponibles.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">$&gt; LOCPATH=\/tmp locale -a | grep en_US\nlocale: No se puede establecer LC_CTYPE como la localizaci\u00f3n predeterminada: No existe el archivo o el directorio\nlocale: No se puede establecer LC_MESSAGES como la localizaci\u00f3n predeterminada: No existe el archivo o el directorio\nlocale: No se puede establecer LC_COLLATE como la localizaci\u00f3n predeterminada: No existe el archivo o el directorio\nen_US\nen_US.iso88591\nen_US.iso885915\nen_US.utf8\n\n$&gt; LC_COLLATE=en_US.UTF-8 sort --debug\nsort: usando las reglas de ordenamiento \u2018en_US.UTF-8\u2019\n\n$&gt; LOCPATH=\/tmp LC_COLLATE=en_US.UTF-8 sort --debug\nsort: usando comparaci\u00f3n simple byte a byte<\/code><\/pre>\n<p><\/p>\n<h1 id=\"zaklyuchenie\">Conclusi\u00f3n<\/h1>\n<p><\/p>\n<p>Si eres un programador que est\u00e1 acostumbrado a pensar que las cadenas son un conjunto de bytes, tu elecci\u00f3n <em>LC_COLLATE=C<\/em>.<\/p>\n<p><\/p>\n<p>Si eres ling\u00fcista o compilador de diccionarios, lo mejor es que compiles tu propia localizaci\u00f3n.<\/p>\n<p><\/p>\n<p>Si eres un usuario com\u00fan, solo necesitas acostumbrarte a que el comando <em>ls -a<\/em> devuelve archivos que comienzan con un punto, mezclados con archivos que comienzan con una letra, y <em>Midnight Commander<\/em>, que utiliza sus funciones internas para ordenar nombres, coloca archivos que comienzan con un punto al inicio de la lista.<\/p>\n<p><\/p>\n<h1 id=\"ssylki\">Enlaces<\/h1>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/unicode.org\/reports\/tr10\/\">Informe \u211610 del algoritmo de colaci\u00f3n de Unicode <\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"http:\/\/www.unicode.org\/Public\/UCA\/latest\/allkeys.txt\">Pesos de caracteres en 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 implementaci\u00f3n de la biblioteca de IBM para trabajar con Unicode. <\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"http:\/\/demo.icu-project.org\/icu-bin\/collation.html\">Prueba de ordenamiento usando <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\">Pesos de caracteres en <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\">Descripci\u00f3n del formato de archivo con pesos <em>open-std.org<\/em> <\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/sourceware.org\/bugzilla\/show_bug.cgi?id=14095\">Discusi\u00f3n sobre la comparaci\u00f3n de cadenas en <em>glibc<\/em><\/a><\/noindex><\/p>\n<p>Fuente: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/503960\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0412\u0441\u0451 \u043d\u0430\u0447\u0430\u043b\u043e\u0441\u044c \u0441 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u043b \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u0430\u0434\u0440\u0435\u0441\u0430\u0445 e-mail \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0439 \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0438, \u0441 \u0434\u043e\u043b\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c\u0438 \u0438\u0437 \u0431\u0430\u0437\u044b \u043e\u0442\u0434\u0435\u043b\u0430 \u043a\u0430\u0434\u0440\u043e\u0432. \u041e\u0431\u0430 \u0441\u043f\u0438\u0441\u043a\u0430 \u0431\u044b\u043b\u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0432 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0432 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0435 \u042e\u043d\u0438\u043a\u043e\u0434 UTF-8 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b \u0441 \u044e\u043d\u0438\u043a\u0441\u043e\u0432\u0441\u043a\u0438\u043c\u0438 \u043a\u043e\u043d\u0446\u0430\u043c\u0438 \u0441\u0442\u0440\u043e\u043a. \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 mail.txt \u0418\u0432\u0430\u043d\u043e\u0432 \u0410\u043d\u0434\u0440\u0435\u0439;ia@example.com \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 buhg.txt \u0418\u0432\u0430\u043d\u043e\u0432\u0430 \u0410\u043b\u043b\u0430;\u043c\u0430\u043b\u044f\u0440 \u0401\u043b\u043a\u0438\u043d\u0430 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-83055","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0412\u0441\u0451 \u043d\u0430\u0447\u0430\u043b\u043e\u0441\u044c \u0441 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u043b \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u0430\u0434\u0440\u0435\u0441\u0430\u0445 e-mail \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0439 \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0438, \u0441.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/kak-linuxovskij-sort-sortiruet-stroki\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"es_ES\" \/>\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\/es\/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\udd47C\u00f3mo sort de Linux ordena cadenas | ProHoster","description":"Introducci\u00f3n Todo comenz\u00f3 con un peque\u00f1o script que deb\u00eda combinar informaci\u00f3n sobre direcciones de e-mail de empleados, obtenidas de la lista de usuarios del mailing, con.","canonical_url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/kak-linuxovskij-sort-sortiruet-stroki","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"es_ES","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\/es\/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\/es\/wp-json\/wp\/v2\/posts\/83055","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/comments?post=83055"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/83055\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=83055"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=83055"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=83055"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}