En los sistemas operativos de la familia Unix, el comando cut permite remover secciones de cada línea de un archivo. Este artículo presenta su uso básico junto con ejemplos desde línea de comandos. Otro de los comandos básicos indispensables para dominar el uso de la terminal



Para entender el funcionamiento de cut vamos a utilizar un archivo como ejemplo:

root@linuxito:/var/log/nginx# head access.log
103.254.56.200 - - [21/Oct/2019:06:28:08 -0400] "GET / HTTP/1.1" 301 186 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36"
18.212.169.157 - - [21/Oct/2019:06:40:57 -0400] "GET /?format=feed&type=rss HTTP/1.1" 301 186 "-" "Winds: Open Source RSS & Podcast app: https://getstream.io/winds/"
46.229.168.153 - - [21/Oct/2019:06:43:43 -0400] "GET /robots.txt HTTP/1.1" 301 186 "-" "Mozilla/5.0 (compatible; SemrushBot/6~bl; +http://www.semrush.com/bot.html)"
46.229.168.148 - - [21/Oct/2019:06:43:46 -0400] "GET /gnu-linux/nivel-alto/147-script-bash-para-verificar-fechas-de-expiracion-de-certificados-x-509 HTTP/1.1" 301 186 "-" "Mozilla/5.0 (compatible; SemrushBot/6~bl; +http://www.semrush.com/bot.html)"
54.36.149.72 - - [21/Oct/2019:06:47:54 -0400] "GET /gnu-linux/nivel-basico/15-miscelaneo/563-habemus-vps HTTP/1.1" 301 178 "-" "Mozilla/5.0 (compatible; AhrefsBot/6.1; +http://ahrefs.com/robot/)"
54.36.148.133 - - [21/Oct/2019:06:55:06 -0400] "GET /gnu-linux/nivel-medio/220-como-determinar-cuanto-espacio-en-disco-ocupa-un-directorio HTTP/1.1" 301 178 "-" "Mozilla/5.0 (compatible; AhrefsBot/6.1; +http://ahrefs.com/robot/)"
18.212.169.157 - - [21/Oct/2019:07:00:06 -0400] "GET /?format=feed&type=rss HTTP/1.1" 301 178 "-" "Winds: Open Source RSS & Podcast app: https://getstream.io/winds/"
46.229.168.148 - - [21/Oct/2019:07:18:34 -0400] "GET /robots.txt HTTP/1.1" 301 186 "-" "Mozilla/5.0 (compatible; SemrushBot/6~bl; +http://www.semrush.com/bot.html)"
46.229.168.140 - - [21/Oct/2019:07:18:34 -0400] "GET /gnu-linux/nivel-medio/305-como-instalar-un-blog-wordpress HTTP/1.1" 301 186 "-" "Mozilla/5.0 (compatible; SemrushBot/6~bl; +http://www.semrush.com/bot.html)"
46.229.168.136 - - [21/Oct/2019:07:22:19 -0400] "GET /component/content/article/2-uncategorised/19-metiendo-mano-en-el-hardware HTTP/1.1" 301 186 "-" "Mozilla/5.0 (compatible; SemrushBot/6~bl; +http://www.semrush.com/bot.html)"

En este caso se trata de un log de accesos de un servidor Web Nginx.

La herramienta cut procesa los archivos de entrada línea por línea, extrayendo sólo la porción indicada por el usuario. Esta porción puede estar acotada por columnas delimitadas, caracteres, o bytes. Veamos ejemplos de cada caso.

Extraer columnas

Extraer columnas separadas por un delimitador en particular:

cut -d DELIMITADOR -f COLUMNAS

El delimitador puede ser cualquier caracter simple (no es posible delimitar con más de un caracter).

Por ejemplo, extraer la primera columna delimitada por espacio en blanco:

root@linuxito:/var/log/nginx# head access.log | cut -d' ' -f1
103.254.56.200
18.212.169.157
46.229.168.153
46.229.168.148
54.36.149.72
54.36.148.133
18.212.169.157
46.229.168.148
46.229.168.140
46.229.168.136

La opción -s se utiliza para ignorar aquellas líneas que no contengan el delimitador buscado. Esta puede ser una opción muy útil a tener en cuenta. Por ejemplo, sólo dos líneas en la salida anterior contienen el caracter &:

root@linuxito:/var/log/nginx# head access.log | cut -d'&' -f1 -s
18.212.169.157 - - [21/Oct/2019:06:40:57 -0400] "GET /?format=feed
18.212.169.157 - - [21/Oct/2019:07:00:06 -0400] "GET /?format=feed

Con esto se evita la necesidad de "grepear" previamente con el objetivo de filtrar.

Seleccionar conjuntos y rangos de columnas

Es posible seleccionar una, un conjunto (separado por coma) o un rango (separado por -) de columnas. Veamos algunos ejemplos.

Las 6 primeras columnas delimitadas por espacio en blanco:

root@linuxito:/var/log/nginx# head access.log | cut -d' ' -f-6
103.254.56.200 - - [21/Oct/2019:06:28:08 -0400] "GET
18.212.169.157 - - [21/Oct/2019:06:40:57 -0400] "GET
46.229.168.153 - - [21/Oct/2019:06:43:43 -0400] "GET
46.229.168.148 - - [21/Oct/2019:06:43:46 -0400] "GET
54.36.149.72 - - [21/Oct/2019:06:47:54 -0400] "GET
54.36.148.133 - - [21/Oct/2019:06:55:06 -0400] "GET
18.212.169.157 - - [21/Oct/2019:07:00:06 -0400] "GET
46.229.168.148 - - [21/Oct/2019:07:18:34 -0400] "GET
46.229.168.140 - - [21/Oct/2019:07:18:34 -0400] "GET
46.229.168.136 - - [21/Oct/2019:07:22:19 -0400] "GET

Las columnas 1 y 3 delimitadas por punto:

root@linuxito:/var/log/nginx# head access.log | cut -d'.' -f1,3
103.56
18.169
46.168
46.168
54.149
54.148
18.169
46.168
46.168
46.168

Todas las columnas desde la 2 en adelante, delimitadas por punto y coma (filtrando sólo las líneas que contienen el delimitador):

root@linuxito:/var/log/nginx# head access.log | cut -d';' -f 2- -s
 WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36"
 SemrushBot/6~bl; +http://www.semrush.com/bot.html)"
 SemrushBot/6~bl; +http://www.semrush.com/bot.html)"
 AhrefsBot/6.1; +http://ahrefs.com/robot/)"
 AhrefsBot/6.1; +http://ahrefs.com/robot/)"
 SemrushBot/6~bl; +http://www.semrush.com/bot.html)"
 SemrushBot/6~bl; +http://www.semrush.com/bot.html)"
 SemrushBot/6~bl; +http://www.semrush.com/bot.html)"

Extraer caracteres por posición

Una opción poco utilizada consiste en seleccionar caracteres por su posición en cada línea:

cut -c CARACTERES

Extraer los caracteres en las posiciones 1, 2 y 3 de cada línea:

root@linuxito:/var/log/nginx# head access.log | cut -b1,2,3
103
18.
46.
46.
54.
54.
18.
46.
46.
46.

Vale aclarar que cut cuenta los caracteres del 1 en adelante (algo extraño para un programador).

Extraer los primeros 60 caracteres de cada línea:

root@linuxito:/var/log/nginx# head access.log | cut -b-60
103.254.56.200 - - [21/Oct/2019:06:28:08 -0400] "GET / HTTP/
18.212.169.157 - - [21/Oct/2019:06:40:57 -0400] "GET /?forma
46.229.168.153 - - [21/Oct/2019:06:43:43 -0400] "GET /robots
46.229.168.148 - - [21/Oct/2019:06:43:46 -0400] "GET /gnu-li
54.36.149.72 - - [21/Oct/2019:06:47:54 -0400] "GET /gnu-linu
54.36.148.133 - - [21/Oct/2019:06:55:06 -0400] "GET /gnu-lin
18.212.169.157 - - [21/Oct/2019:07:00:06 -0400] "GET /?forma
46.229.168.148 - - [21/Oct/2019:07:18:34 -0400] "GET /robots
46.229.168.140 - - [21/Oct/2019:07:18:34 -0400] "GET /gnu-li
46.229.168.136 - - [21/Oct/2019:07:22:19 -0400] "GET /compon

Extraer los caracteres del 30 al 60 inclusive:

root@linuxito:/var/log/nginx# head access.log | cut -c30-60
19:06:28:08 -0400] "GET / HTTP/
19:06:40:57 -0400] "GET /?forma
19:06:43:43 -0400] "GET /robots
19:06:43:46 -0400] "GET /gnu-li
:06:47:54 -0400] "GET /gnu-linu
9:06:55:06 -0400] "GET /gnu-lin
19:07:00:06 -0400] "GET /?forma
19:07:18:34 -0400] "GET /robots
19:07:18:34 -0400] "GET /gnu-li
19:07:22:19 -0400] "GET /compon

Extraer bytes

Es similar a la extracción de caracteres, pero a nivel byte. Tener en cuenta que los caracteres multi-byte (por ejemplo aquellos soportados por la codificación de caracteres UTF-8) ocupan más de un byte, por ello se dispone de esta opción que opera a nivel byte:

cut -b BYTES

Modificar el delimintador en la salida

Es posible reemplazar el delimitador en la salida mediante la opción --output-delimiter. Esto puede ser útil, por citar un ejemplo, para convertir un archivo a CSV.

Seleccionar las primeras 5 columnas delimitadas por espacio y cambiar el delimitador por punto y coma:

root@linuxito:/var/log/nginx# head access.log | cut -d' ' -f-5 --output-delimiter=';'
103.254.56.200;-;-;[21/Oct/2019:06:28:08;-0400]
18.212.169.157;-;-;[21/Oct/2019:06:40:57;-0400]
46.229.168.153;-;-;[21/Oct/2019:06:43:43;-0400]
46.229.168.148;-;-;[21/Oct/2019:06:43:46;-0400]
54.36.149.72;-;-;[21/Oct/2019:06:47:54;-0400]
54.36.148.133;-;-;[21/Oct/2019:06:55:06;-0400]
18.212.169.157;-;-;[21/Oct/2019:07:00:06;-0400]
46.229.168.148;-;-;[21/Oct/2019:07:18:34;-0400]
46.229.168.140;-;-;[21/Oct/2019:07:18:34;-0400]
46.229.168.136;-;-;[21/Oct/2019:07:22:19;-0400]

Para más información, consultar la página de manual de cut:

man cut


Tal vez pueda interesarte


Compartí este artículo