Este documento está disponible en los siguientes idiomas: English Castellano Deutsch Francais Nederlands Russian Turkce |
por Manuel Muriel Cordero Sobre el autor: Manuel Muriel Cordero es estudiante de la Facultad de informática y estadística de Sevilla. Contenidos: |
Resumen:
En el articulo anterior de esta serie se dio un repaso a los aspectos más generales de Linux. Con él se introdujo al lector en los asuntos mínimos para entablar un uso manejable sobre el sistema operativo. El usuario puede desear conocer herramientas típicas de los Unix , y por extensión Linux, para poder controlar la administración de archivos de forma más eficiente. En este artículo se pretende explicar un conjunto de herramientas un poco más avanzadas pero básicas para esa función.
Antes de empezar a detallarlas el lector debe conocer un poco el porque de sus peculiaridades. Kem Thompsom y Denis Ritchie cuando crearón Unix a principios de los sesenta tuvieron en mente crear un sistema operativo que facilitase la labor a los programadores. A la conclusión que llegaron es que la mejor forma es establecer un conjunto definido de pequeñas herramientas que hagan una determinada labor muy bien. A partir de la unión de esas herramientas se pueden realizar labores más complejas mediante la comunicación de los resultados de unas se conviertan en entradas de otra.
Esa forma de trasmitirse la información se realiza con el uso de la entrada y salida estandar ( pantalla y teclado ). Pero gracias a la existencia de las tuberias y redireciones ( que vimos en el capítulo anterior ) se consiguen esos resultados.
Se puede apreciar en un ejemplo. Si un usuario introduce esta linea:
$ who | grep pepe
who y grep son programas distintos separados por la tubería "|" . who nos muestra un listado de todos los usuarios conectados al ordenador en el momento dado. Su salida habitual sería algo parecido a esto:
$ who manolo tty1 Dec 22 13:15 pepe ps/2 Dec 22 14:36 root tty2 Dec 22 10:03 pepe ps/2 Dec 22 14:37
Lo que devuelve who se divide en 4 campos separados por tabuladores. Los cuales son nombre de usuario (login) , terminal en el que esta conectado , fecha y hora de inicio de la conexión.
"grep pepe" por su parte busca las lineas de esa salida que contengan la secuencia "pepe".
De esta forma la salida es:
$ who | grep pepe pepe ps/2 Dec 22 14:36 pepe ps/2 Dec 22 14:37
Por ejemplo si ahora el usuario en cambio quiere algo más simple, es decir saber si está o no está conectado mediante el número de conexiones que tiene en este momento se debe usar la utilidad wc.
wc es contador de letras,palabras y lineas. En este caso solo precisamos saber el número de lineas así que se ha de utilizar la opción -l
$ who | grep pepe | wc -l 2
pepe esta conectado en 2 terminales
Si ahora probamos con antonio
$ who | grep antonio | wc -l 0
antonio no esta conectado
Richar Stallman , fundador del proyecto GNU, observó que es éticamente discutible la tiranía de las grandes empresas del software sobre el mercado que impide un avance racional de la informática. Tras trabajar en el MIT desarollando el editor Emacs no le agradó que su trabajo fuese utilizado por las marcas comerciales para crear versiones propetarias. Ante esa situacion decidio crear un proyecto con vista que el fuente de los programas fuese accesible por todo el mundo. Ese es el GNU. Su objetivo era crear todo un sistema operativo de software abierto . El trabajo comenzo por desarrollar una versión libre de Emacs , un compilador ( el GCC ) y además el conjunto habitual de herramientas típicas de los sistemas Unix. Estas son las que este artículo analiza.
En el ejemplo anterior hemos visto básicamente cual es el objetivo de grep . Ahora se especifica con más detalle.
grep básicamente funciona de esta manera:
$ grep [-opciones] patrón ficheros
Las opciones más comunes son:
-n antepone a cada linea emparejada con su número de línea (útil para
buscar algo en un fichero muy largo y saber donde esta
especificamente)
-c imprime solo el número de coincidencia encontradas
-v solo se buscan las no coincidencias ( cuando lo que buscamos es lo
que no coincide con el patrón )
El patrón es cualquier conjunto de caracteres que se busca. Hay que indicar es que si van acompañados de un espacio grep confundira el patrón con los ficheros a buscar, eso se soluciona con la ayuda de los caracteres ".Por ejemplo:
$ grep "Hola mundo" fichero
Si buscamos alguna cadena que contenga un comodín , apóstrofes , comillas , redirreciones o barras del tipo "\", se deberá anteponer una barra "\" para asi indicar de que buscamos esa caracter en si y no la substitución del comodín , o que iniciamos una cadena de varias palabras .
$ grep \*\"\'\?\< fichero Esto es una cadena chunga -> *"¿<
grep y otros herramientas GNU son capaces de realizar busquedas más avanzadas. Eso se consigue con ayuda de las expresiones regulares. Las expresiones regulares cumplen una función parecida a los comodines en el shell, o sea hacen sustituciones de caracteres o conjunto de caracteres. Unos ejemplos:
$ grep c.n
busca todas las ocurrencias que tenga una cadena con una c , cualquier letra y una t
$ grep [Bc]el
busca las ocurrencias Bel y cel.
$ grep [m-o]ata
Das las lineas que contengán mata, nata y oata.
$ grep [^m-o]ata
Da las lineas que contenga una cadena terminada en ata y que no contenga como primera letra m,m y o
$ grep "^Martin come"
Como salida las lineas que comienzen con Martin come , ojo vease que no esta entre corchetes , en este caso no es una negación de conjunto como en el anterior ejemplo sino como comienzo de línea.
$ grep "durmiendo$"
Encontrará las lineas terminadas en durmiendo. $ substituye a un fin de línea.
$ grep "^Caja San Fernando gana la liga$"
Busca aquellas lineas que sean exactamente eso.
Por supuesto estos caracteres para eliminar su significado de sustitución hay que anteponerles la obligatoria "\". Por ejemplo:
$ grep "E\.T\."
Buscara la secuencia E.T.
Este comando se encarga de la busqueda de ficheros. En otro artículo de esta revista se ha explicado con bastante detalle. Así como la cosa no es redescrubir la rueda solo hago referencia a él.
En Unix la información solía guardarse en ficheros de texto ASCII organizados por campos verticales separados con un caracter diferenciador , este solia ser un tabulador o el carácter ":". Una de las necesidades que se suele producir en estos casos es separar los campos de un fichero y unirlos en otro. cut y paste realizan ese trabajo.
Vamos a usar como ejemplo el fichero /etc/passwd encargado de gestionar los usuarios. Su contenido se compone de 7 campos separados por ":" . Los campos son respectivamente y en este orden login,clave encriptada , identificación de usuario , identificación de grupo , geco , directorio de inicio de usuario y shell que usa.
He aquí un extracto típico de ese archivo.
root:x:0:0:root:/root:/bin/bash murie:x:500:500:Manuel Muriel Cordero:/home/murie:/bin/bash practica:x:501:501:Usuario de practicas para Ksh:/home/practica:/bin/ksh wizardi:x:502:502:Wizard para nethack:/home/wizard:/bin/bash
Si por ejemplo ahora queremos ahora emparejar los usuarios con los login que usa debemos cortar los campos 1 y 7. Manos a la obra:
$ cut -f1,7 -d: /etc/passwd root:/bin/bash murie:/bin/bash practica:/bin/ksh wizard:/bin/bash
-f expecifica los campos a visualizar -d indica el separador a usar ( por defecto el tabulador ) y por último se encuentra el fichero a listar.
También es posible especificar intervalos de campos:
$ cut -f5-7 -d: /etc/passwd root:/root:/bin/bash Manuel Muriel Cordero:/home/murie:/bin/bash Usuario de practicas para Ksh:/home/practica:/bin/ksh Wizard para nethack:/home/wizard:/bin/bash
Dejo al lector como ejercicio averiguar el porqué de esa salida.
Ahora supongamos que hemos redirigido la salida con la ayuda de ">" a 2 ficheros y queremos unir las 2 salidas. Para ello esta paste.
$ paste salida1 salida2 root:/bin/bash:root:/root:/bin/bash murie:/bin/bash:Manuel Muriel Cordero:/home/murie:/bin/bash practica:/bin/ksh:Usuario de practicas para Ksk:/home/practica:/bin/ksh wizard:/bin/bash:Wizard para nethack:/home/wizard:/bin/bash
Por ejemplo supongamos ahora que deseamos de un /etc/passwd ordenada según el geco. Para ello recurrimos a sort, la herramienta de ordenación.
$ sort -t: +4 /etc/passwd murie:x:500:500:Manuel Muriel Cordero:/home/murie:/bin/bash practica:x:501:501:Usuario de practicas para Ksh:/home/practica:/bin/ksh wizard:x:502:502:Wizard para nethack:/home/wizard:/bin/bash root:x:0:0:root:/root:/bin/bash
Se puede apreciar que ha ordenado la salida , pero siguiendo el criterio de la tabla ASCII , si deseamos que no diferencia entre mayúsculas y minúsculas se haría con:
$ sort -t: +4f /etc/passwd murie:x:500:500:Manuel Muriel Cordero:/home/murie:/bin/bash root:x:0:0:root:/root:/bin/bash practica:x:501:501:Usuario de practicas para Ksh:/home/practica:/bin/ksh wizard:x:502:502:Wizard para nethack:/home/wizard:/bin/bash
-t es la opción que indica que separador se usa . +4 se refiere a cuantos campos hay que saltar antes de iniciar la ordenación. f indica que se ignore las diferencias entre mayúsculas y minúsculas
Se puede realizar una ordenación mucho más refinada. Por ejemplo ordenado primero de forma inversa según el shell que use y luego por el geco:
$ sort -t: +6r +4f /etc/passwd practica:x:501:501:Usuario de practicas para Ksh:/home/practica:/bin/ksh murie:x:500:500:Manuel Muriel Cordero:/home/murie:/bin/bash root:x:0:0:root:/root:/bin/bash wizard:x:502:502:Wizard para nethack:/home/wizard:/bin/bash
Ahora supóngase que disponemos un fichero en el que se archiva las personas y las deudas en cuestión de préstamos que tiene con usted. Un ejemplo "manga":
Son Goku:23450 Son Gohan:4570 Picolo:356700 Ranma 1/2:700
Si usted desea saber a cual primero le tiene que mandar el matón :-) deseará obtener una salida ordenada según morosos.
Si se realiza esta prueba se puede observar que:
$ sort +1 deudas Ranma 1/2:700 Son Gohan:4570 Son Goku:23450 Picolo:356700
Esto no es precisamente lo que se espera debido a que se ha realizado una busqueda alfabética con un número diferente de digitos. La solución reside en la opcion n:
$ sort +1n deudas Picolo:356700 Son Goku:23450 Son Gohan:4570 Ranma 1/2:700
Las opciones basicas de sort son estas
+n.m se salta los n primeros campos y los m siguientes caracteres
antes de empezar la ordenación.
-n.m para la ordenación al llegar al n-esimo campo y m caracteres
despues
y como modificadores de los parametros son:
-b ignora espacios en blanco iniciales
-d orden de diccionario ( solo se tienen en cuenta letras , numeros y
espacios)
-f ignora la distinción entre mayúsculas y minúsculas.
-n orden aritmético
-r orden inverso
wc como se ha visto ya es un contador de letras,lineas y palabras. Por defecto al introducir como parametro un fichero da como salida el número de lineas, palabras y caracteres que lo componen
Con las opciones podemos variar esa salida
-l solo da las lineas
-w solo da las palabras
-c solo da los caracteres
A veces es necesario saber en que se diferencián 2 versiones de un fichero. Este se usa especialmente en programación cuando hay varias personas trabajando en un mismo proyecto modificando los fuentes de los programas. Si se precisa saber las variaciones de una versión de otra se recurre a estas herramientas.
cmp es la más básica de todas. Compara dos ficheros e indica , si la hay , el lugar donde se produce la primera diferencia (número de caracter y línea de la diferencia)
$ cmp antigua nueva antigua nueva differ: char 11234, line 333
comm es algo más avanzado. Su salida se produce en 3 columnas. La primera contiene las lineas únicas del primer fichero, la segunda las únicas del segunda y la tercera las comunes. Dispone de parametros númericos que establecen si deseas eliminar alguna de esas columnas. Son la -1 , -2 y -3 que indican a comm que no visualizen la primera, segunda y tercera columna. Con este ejemplo se observa las lineas que sólo están en el primer fichero y las comunes.
$ comm -2 antigua nueva
Por último está diff. Es una herramienta fundamental en programación de proyectos avanzados. Si alguna vez ha bajado un kernel para compilarlo sabra que puede bajarse los fuentes de la nueva o bajarse el patch con respecto a la anterior, que suele ser un fichero mas pequeño . Ese patch suele terminar en .diff lo que indica que es el resultado de una salida diff. Esta herramienta contiene una serie de comandos de editor ( vi , rcs ) de tal manera que se hagan idénticos los 2 ficheros. También es aplicable a directorios y todos los archivos que lo contienen. La utilidad es muy clara, al tener que bajar menor cantidad de fuente ( solo los cambios ) se aplica el parche ( con patch ) y se vuelve a compilar. Sin parametros la salida específica en estos formatos como se deben hacer los cambios de tal manera que el primero sea igual al segundo con comandos vi.
$ diff antigua nueva 3c3 < El Hobbit --- > El Señor de los Anillos 78a79,87 > Tres anillos para los Reyes Elfos bajo el cielo. > Siete pera los Señores Enanos en casas de piedra. > Nueve para los Hombres Mortales condenados a morir. > Uno para el Señor Oscuro, sobre el trono oscuro > en la tierra de Mordor donde se extienden las Sombras. > Un Anillo para gobernarlos a todos. Un Anillo para encontrarlos, > un anillo para atraerlos a todos y atarlos a las tinieblas > en la tierra de Mordor donde se extienden las Sombras.
3c3 expresa que se debe cambiar la línea 3 , quitando "El Hobbit" y substituyendolo por "El Señor de los Anillos". 78a79,87 indica que se debe insertar unas nuevas lineas 79 a la 87.
uniq es el encargado de eliminar las redundancias. Por ejemplo si deseamos obtener un listado de la gente conectada al ordenador en un momento dado deberemos hacer uso de who y de cut.
$ who | cut -f1 -d' ' root murie murie practica
El resultado no es del todo perfecto. Falta eliminar la doble aparición de murie. Dicho y hecho.
$ who | cut -f1 -d' ' | uniq root murie practica
Como nota indicar que el -d' ' indica que el separador es el espacio en blanco ya que who no separa usando tabuladores.
sed es una de las herramientas más peculiares de Unix. sed significa Stream Editor ( o sea editor de flujo ) . Los editores suelen aceptar de forma interactiva las modificaciones que se desean insertar. Sed nos permite crear pequeños programas "shell scripts" parecidos a los batch de MS-DOS . Sed nos dan la capacidad de modificar de forma automática el contenido de un fichero , permitiendonos crear shell scripts que lo modifiquen "on the fly". Las capacidades de este editor son muy completas y por la extensión que tomaría el artículo no se verán aquí, por lo cual se adoptara una breve introducción dejando al usuario interesado recurrir a la documentación en formato de man e info que contiene linux sobre todos sus comandos.
Sed suele llamarse de esta forma:
$ sed 'comando-sed' fichero
Por ejemplo tengamos un fichero en el que deseamos reemplazar todos las apariciones de "Manolo" por "Fernando" . Manos a la obra:
$ sed 's/Manolo/Fernando/g' archivo
Y devuelve por salida estandar las modificaciones. Si se desea conservar el resultado se redigirá con ">"
Los usuarios de vi reconecerán inmediatamente que se trata de un comando típico de vi de busqueda y sustitución. En realidad los comandos de tipo ":" ( los que invocan a ex ) se pueden usar con sed.
La estructura de los ordenes sed consiste en indicar primero una cadena ( o secuencia de cadenas ) sobre las que actuar y luego el comando. Para indicar una cadena se puede indicar un numero, un intervalo de numeros o buscar un patron.
Los comandos usuales de sed Comando Acción ------- ------ a\ añade las lineas siguientes a las lineas afectadas c\ cambia las lineas afectadas por las lineas siguientes d borra las lineas afectadas g hace sustituciones generales, de todos los patrones localizados inserta en lugar de limitarse al primero i\ inserta las lineas siguientes a las afectadas p imprime la línea, incluso con la opción -n q abandonada (quit) cuando se alcanza la línea especificada r fichero lee un fichero , añadiendo el contenido a la salida s/uno/dos sustituye la cadena "uno" por "dos" w fichero copia esa linea a otro fichero = imprime el número de línea ! comando aplica un comando a dicha línea
Con sed se puede especificar sobre que lineas o conjunto de lineas se aplica el comando:
$ sed '3d' archivo
Borrará la tercera línea del archivo
$ sed '2,4s/e/#/' fichero
Substituye el caracter e por # en las lineas del 2 a la 4 inclusive.
También es posible realizar comandos sobre lineas que contengan una determinada cadena haciendo uso , si se desea , de expresiones regulares explicadas con anterioridad.
$ sed '/[Qq]ueen/d' canciones
Borra todas las lineas que contengan la cadena "Queen" o "queen".
Con la ayuda de expresiones regulares podemos por ejemplo eliminar las lineas vacias de un fichero.
$ sed '/^$/d' archivo
Aunque esto no borrará las cadenas que contengan espacios. Con esta versión además se consigue ese propósito.
$ sed '/^ *$/d' archivo
La secuencia ' *' indica que se debe buscar cualquier combinación de cero o mas apariciones del patrón ' '.
$ sed '/InitMenu/a\ > gvim gvim.xpm exec gvim &' .xvwmrc Este ejemplo buscaria una linea que contenga la cadena InitMenu y despues de esa le añadiria esa cadena.
Por último y no menos importante esta el comando awk. Para los que se extrañen por ese peculiar nombre , este proviene de sus creadores originales Alfred Aho, Brian Kernighan y Peter Weinberger.
La utilidad awk es una de las más interesantes de los sistemas Unix. Es un herramienta bastante compleja y avanzada que permite desde la linea de comandos realizar un variado conjunto de operaciones.
Cabe indicar de que awk y sed forman pieza clave de los shell scripts más complejos. Puede resultar realmente impresionante lo que se puede llegar a hacer sin hacer uso para nada de C o cualquier otro lenguaje compilado. Cabe destacar que por ejemplo el setup de la distribucion de slakware así como muchos CGI del web son en realidad shell scripts.
Últimamente el uso de las herramientas de la línea de comandos ha sido algo denostado, achacandole demasiada antiguedad para los entornos de ventanas que se usan actualmente así como la llegada de lenguaje Perl que pretende ser un substituto de shell scripting dan a indicar que estas herramientas están condenadas al olvido. En mi experiencia he podido comprobar que muchas aplicaciones ( incluso un pequeño gestor de base de datos ) es cuestión de pocas líneas de código en shell script.
Es aquí donde awk junto con sed pueden realizar una gran labor sobre información almacenada en formato ASCII. Con ellos podemos realizar labores iguales a la suma de un pequeño gestor de base de datos más una hoja de cálculo.
Supongamos una factura en la que se indica en un fichero los artículos comprados y su precio de venta al público. Por ejemplo este archivo "compras":
naranjas 5 250 peras 3 120 manzanas 2 360
Se trata de un fichero con 3 campos separados por tabuladores. Ahora se desea crear un cuarto campo con el precio total por cada producto.
$ awk '{total=$2*$3; print $0 , total }' compras naranjas 6 250 1250 peras 3 120 360 manzanas 2 360 720
total es una variable al que se le asignan los valores multiplicados de los campos segundo y tercero, luego a cada linea se imprime la linea completa ($0) y el total por linea.
awk es casi un entorno de programación por si solo , ideal para el tratamiento automatizado de información en ficheros de texto. Si el usuario ha descubierto con interes esta herramienta le animo a seguir descubriendo sus peculiaridades en las paginas man e info de su sistema.
Ya se ha referido a ellos anteriormente. Los shell scripts son secuencias de instrucciones ( comandos del sistema ) que se deben realizar.
Los shell scripts tienen como hermanos a los archivos batch de DOS. Con ellos el usuario esta habilitado para crear sus propios comandos a partir de combinaciones de otros.
Los shell scripts son capaces , por supuesto , de aceptar parametros, estos se almacenan en las variables $0 ( nombre del comandos ) $1 , $2 , ... , $9. Para referirse a los $1 al $9 se puede hacer uso de $*
Los shell scripts se pueden crear con cualquier editor. Para ejecutarlos se puede hacer con:
$ sh shell-script
o mejor darle permisos de ejecución al archivo con
$ chmod 700 shell-script
Y luego se puede ejecutar con sólo
$ shell-script
Por ahora se deja a los shell scripts y así terminamos este artículo. Ya en proximos números se retomará el tema. En el proximo artículo se hablará acerca de los editores más comunes en los Unix. El vi y el emacs. EL conocimiento de su uso es fundamental para cualquier usuario de Linux.
Este artículo es introductorio y si el autor lo cree conveniente puede estudiar con más detalles en otros articulos de LinuxFocus como: Find Expresiones regulares Awk
El señor de los anillos . Autor J.R.R Tolkien . Edicciones Minotauro (c) 1997
|
Contactar con el equipo de LinuFocus
© Manuel Muriel Cordero, FDL LinuxFocus.org Pinchar aquí para informar de algún problema o enviar comentarios a LinuxFocus |
2001-07-02, generated by lfparser version 2.9