Quiero eliminar líneas duplicadas de un archivo con palabras en escritura siríaca. El archivo fuente tiene 3 líneas, la primera y la tercera son idénticas.
$ cat file.txt
ܐܒܘܢ
ܢܗܘܐ
ܐܒܘܢ
Cuando uso sort
y uniq
, el resultado supone que las 3 líneas son idénticas, lo cual es incorrecto:
$ cat file.txt | sort | uniq -c
3 ܐܒܘܢ
Establecer explícitamente el idioma siríaco tampoco ayuda.
$ LC_COLLATE=syr_SY.utf8 cat file.txt | sort | uniq -c
3 ܐܒܘܢ
¿Por qué sucedería eso?
Estoy usando Kubuntu 18 y bash, si eso importa.
Respuesta aceptada:
La implementación GNU de uniq
como se encuentra en Ubuntu, con -c
, no informa recuentos de idénticos contiguos líneas pero recuentos de líneas contiguas que ordenan lo mismo¹.
La mayoría de las configuraciones regionales internacionales en los sistemas GNU tienen el error de que muchos caracteres completamente no relacionados se han definido con el mismo orden de clasificación, la mayoría de ellos porque su orden de clasificación no está definido en absoluto. La mayoría de los demás sistemas operativos se aseguran de que todos los caracteres tengan un orden de clasificación diferente.
$ expr ܐ = ܒ
1
(expr
's =
operador, para argumentos que no son numéricos, devuelve 1 si los operandos tienen el mismo orden, 0 de lo contrario).
Es lo mismo con ar_SY.UTF-8
o en_GB.UTF-8
.
Lo que necesitaría es una configuración regional en la que a esos caracteres se les haya dado un orden de clasificación diferente. Si Ubuntu tuviera configuraciones regionales para el idioma siríaco, podría esperar que esos caracteres tuvieran un orden de clasificación diferente, pero Ubuntu no tiene tales configuraciones regionales.
Puede mirar la salida de locale -a
para obtener una lista de las configuraciones regionales admitidas. Puede habilitar más locales ejecutando dpkg-reconfigure locales
como root
. También puede definir más locales manualmente usando localedef
basado en los archivos de definición en /usr/share/i18n/locales
, pero no encontrará datos para el idioma siríaco allí.
Tenga en cuenta que en:
LC_COLLATE=syr_SY.utf8 cat file.txt | sort | uniq -c
Solo está configurando la variable LC_COLLATE para el cat
comando (que no afecta la forma en que genera el contenido del archivo, cat
no le importa la intercalación ni siquiera la codificación de caracteres, ya que no es una utilidad de texto). Te gustaría configurarlo para ambos sort
y uniq
. También querrá configurar LC_CTYPE
a una configuración regional que tenga un juego de caracteres UTF-8.
Como su sistema no tiene syr_SY.utf8
locale, eso es lo mismo que usar el C
configuración regional (la configuración regional predeterminada).
En realidad, aquí la configuración regional C o C.UTF-8 es probablemente la configuración regional que le gustaría usar.
En esas configuraciones regionales, el orden de intercalación se basa en el punto de código, punto de código Unicode para C.UTF-8, valor de byte para C, pero termina siendo lo mismo que la codificación de caracteres UTF-8 tiene esa propiedad.
$ LC_ALL=C expr ܐ = ܒ
0
$ LC_ALL=C.UTF-8 expr ܐ = ܒ
0
Entonces con:
(export LANG=ar_SY.UTF-8 LC_COLLATE=C.UTF-8 LANGUAGE=syr:ar:en
unset LC_ALL
sort <file | uniq -c)
Tendría un LC_CTYPE con UTF-8 como juego de caracteres, un orden de clasificación basado en el punto de código y otras configuraciones relevantes para su región, por ejemplo, mensajes de error en siríaco o árabe si GNU coreutils sort
o uniq
los mensajes se habían traducido a esos idiomas (todavía no lo han hecho).
Si no te importan esos otros configuración, es igual de fácil (y también más portátil) de usar:
<file LC_ALL=C sort | LC_ALL=C uniq -c
O
(export LC_ALL=C; <file sort | uniq -c)
como ya ha mostrado @isaac.