Saltar la navegación

uniq

El comando uniq suprime o informa de líneas duplicadas consecutivas que contiene un fichero o la entrada estándar.

La sintaxis general es:

uniq  [opción...]  [ fichero_entrada  [fichero_salida] ]

Si fichero_salida no se especifica, entonces la información se manda a la salida estándar y si tampoco se especifica fichero_entrada, entonces se lee de la entrada estándar, esto último sería equivalente a poner un carácter - como fichero de entrada, lo cual es obligatorio si se ha especificado fichero_salida y queremos leer de la entrada estándar.

Como el filtro uniq elimina lineas duplicadas consecutivas es muy habitual usarlo junto con el filtro sort.

Por defecto el funcionamiento de uniq es eliminar todas las líneas repetidas consecutivamente menos una. En el ejemplo siguiente queremos ver cuantas máscaras de permisos distintas hay en el directorio de trabajo.

$ ls -l
total 60
-rw-r--r-- 1 usuario vboxsf 25969 sep  7 13:10 f1.txt
-rw-r--r-- 1 usuario vboxsf 20981 sep  7 13:10 f2.txt
-rw-rw-rw- 1 usuario vboxsf    49 sep  7 13:10 f3.txt
-rw-r--r-- 1 usuario vboxsf    48 sep  7 13:10 f4.txt
$ ls -l | tail -n +2 | cut -c 2-10 | sort | uniq
rw-r--r--
rw-rw-rw-

La opción -u nos muestra solo las líneas no repetidas:

$ ls -l | tail -n +2 | cut -c 2-10 | sort | uniq -u
rw-rw-rw-

 Y la opción -d solo muestra las líneas que se repiten pero mostrando una única instancia:

$ ls -l | tail -n +2 | cut -c 2-10 | sort | uniq -d
rw-r--r--

No debemos olvidar, que las repeticiones de líneas se entienden por grupos de líneas consecutivas, por lo que si una línea está repetida pero en posiciones alejadas, no consecutivas, para uniq serán líneas diferentes. Podemos ver esto en los siguientes ejemplos donde no se aplica el filtro sort:

$ ls -l
total 60
-rw-r--r-- 1 usuario vboxsf 25969 sep  7 13:10 f1.txt
-rw-r--r-- 1 usuario vboxsf 20981 sep  7 13:10 f2.txt
-rw-rw-rw- 1 usuario vboxsf    49 sep  7 13:10 f3.txt
-rw-r--r-- 1 usuario vboxsf    48 sep  7 13:10 f4.txt
$ ls -l | tail -n +2 | cut -c 2-10 | uniq
rw-r--r--
rw-rw-rw-
rw-r--r--
$ ls -l | tail -n +2 | cut -c 2-10 | uniq -u
rw-rw-rw-
rw-r--r--
$ ls -l | tail -n +2 | cut -c 2-10 | uniq -d
rw-r--r--

Muy parecida a la opción -d es la opción -D, ya que esta última muestra todas las líneas repetidas consecutivas y no solo una como hace -d:

$ ls -l | tail -n +2 | cut -c 2-10 | uniq -D
rw-r--r--
rw-r--r--

Podemos ayudarnos de uniq para contar cuántas veces se repiten las líneas, para ello usamos la opción -c:

$ ls -l | tail -n +2 | cut -c 2-10 | uniq -c
      2 rw-r--r--
      1 rw-rw-rw-
      1 rw-r--r--
$ ls -l | tail -n +2 | cut -c 2-10 | sort | uniq -c
      3 rw-r--r--
      1 rw-rw-rw-

Hasta ahora se ha tenido en cuenta la línea completa para ver si se repite o no, pero existen opciones que permiten solo tener en cuenta parte de la línea. Con la opción -f podemos evitar comparar los primeros n campos. Los campos para uniq son delimitados por secuencias de espacios y/o tabuladores. El primer campo es el número cero.

$ cat f5.txt
a    l    b
b    l    b
c    a    b
b    a    b
$ uniq -f 1 f5.txt
a    l    b
c    a    b
$ uniq -f 2 f5.txt
a    l    b

Si lo que queremos es saltar los n primeros caracteres usaríamos la opción -s.

$ ls -l
total 64
-rw-r--r-- 1 usuario vboxsf 25969 sep  7 13:10 f1.txt
-rw-r--r-- 1 usuario vboxsf 20981 sep  7 13:10 f2.txt
-rw-rw-rw- 1 usuario vboxsf    49 sep  7 13:10 f3.txt
-rw-r--r-- 1 usuario vboxsf    48 sep  7 13:10 f4.txt
-rw-r--r-- 1 usuario vboxsf    24 sep  8 20:36 f5.txt
$ ls -l | tail -n +2 | tr -s ' ' | cut -d ' ' -f 1-4 | uniq -s 10
-rw-r--r-- 1 usuario vboxsf

También, con la opción -w podemos hacer que las comparaciones se realicen solo con los n primeros caracteres.

$ uniq -w 1 f5.txt
a    l    b
b    l    b
c    a    b
b    a    b
$ sort f5.txt | uniq -w 1
a    l    b
b    a    b
c    a    b

Por último, la opción -i hace que las comparaciones no tengan en cuenta la diferencia entre mayúsculas y minúsculas.

 

Licencia: licencia de software libre GPL