Compartir

Compartir en GNU Social Compartir en Diaspora*

Disección de un script

Aprovechando el último envío (sí ese, el del meme) voy a destripar un poco el script utilizado. Para los que no hayan leido esa entrada y no les apetezca hacerlo, transcribo a continuación el script:
history|awk '{print $2}'|awk 'BEGIN {FS="|"} {print $1}'| sort| uniq -c| sort -rn |head -10
Antes de seguir aclaremos que el script anterior es una copia del publicado por Michael Stutz aquí siendo una parte de un gran artículo en el que describe una amplia variedad de trucos de shell. Pasemos ya a la disección del script y antes de empezar por el principio voy a explicar mínimamente el concepto de "tubería" en los shell-scripts. Muchos de los comandos que se utilizan en una shell muestran por pantalla (realmente por la salida estándar) el resultado de una ejecución, así "less mifichero" vuelca a la pantalla el contenido de mifichero paginándolo. Igualmente hay muchos comandos que pueden recibir (por la entrada estándar) la información que deben tratar, por ejemplo y siguiendo con el comando less esta información le puede llegar directamente del fichero que se le ponga (en el ejemplo anterior mifichero) pero también le podría llegar si fueramos capaces de enviarle un conjunto de datos a la entrada estándar, es decir si quisieramos sacar el contenido de un directorio (con ls -l) podriamos intentar que su resultado que en principio va a la salida estándar se redirigiera a la entrada del comando less (ahora veremos como) para que este comando muestre el resultado de ls -l pero paginándolo. Para hacer esto se utilizan las tuberías, que no es más que algo (el caracter |) que se pone entre dos comandos de forma que la shell lo interpreta de tal forma que la salida del primer comando se la envía a la entrada del segundo comando. Es decir en el último ejemplo hariamos
ls -l | less
Ahora ya sí pasamos con el script que nos saca los 10 comandos más utilizados en un terminal. Con el primer comando (history) recuperamos el historial de comandos del usuario que tiene la forma
... n comando n+1 otrocomando parametros | mascomandos masparametros n+2 comando|otrocomando ...
Con awk '{print $2}' nos quedamos con el segundo campo de la lista anterior (teniendo en cuenta que considera que cada campo está separado de los demás por espacios), es decir su ejecución a partir de lo que le envía el history será:
... comando otrocomando comando|otrocomando ...
El segundo awk es para que de los comandos del tipo comando1|comando2 (así sin espacios entre ellos) se quede únicamente con comando1. La parte BEGIN {FS="|"} le indica que debe tomar como separador de campos el caracter "|", si no se le indicara nada cogería como separador el espacio. En el ejemplo quedará:
... comando otrocomando comando ...
A continuación se le "enchufa" al sort para ordenarlo de forma que los comandos que son iguales queden juntos para luego "contarlos":
... comando comando otrocomando ...
El resultado del sort se lo pasamos a uniq que con el parámetro -c nos elimina los duplicados pero contando cuantos hay de cada uno:
... 1 otrocomando 2 comando ...
A continuación volvemos a ordenarlo (ahora con sort -rn) de forma que quede ordenado por el número de veces que se repite sacandolos de mayor a menor:
... 2 comando ... 1 otrocomando ...
Y finalmente con head -10 nos quedamos con los primeros 10 del resultado anterior, es decir, en este caso con los 10 comandos más usados en la shell.