LUG.ro
GNU/Linux
LUG.ro - GNU/Linux Users
Group Rosario
Rosario
en


Tema 7



Programas de edición de consola







Por mas que queramos convencernos de que el usar el comando "cat" y redirigirlo a un archivo nos va a ser suficiente para poder trabajar con texto no podremos seguir engañándonos por mucho tiempo.

Si existe algo que sé a apreciado mucho en lo referente a la informática tanto en el hogar como en la oficina, es la manera más sencilla que se tiene de editar textos y trabajar con ellos de una forma eficiente, produciendo así también una retroalimentación para que estos entornos vayan mejorando.

Existen conjuntos de aplicaciones como el Star Office de Sun o Corel Word Perfect que nos permiten hacer el trabajo de edición de texto mas fácilmente.

Pero también existe toda una gama de editores de textos, en línea y fuera de línea, que permiten hacer el trabajo en ocasiones cuando no se cuenta con ningún otro editor.

En este capitulo trataremos de proporcionar una guía sobre las principales herramientas para manipular archivos de texto. El cómo los usemos y cual de ellos adoptemos dependerán de las circunstancias y los gustos del usuario.

Los dos primeros editores son el vi "Visual Editor" y el Emacs con los cuales podremos interactuar para hacer la edición del contenido de un archivo.

Luego veremos a un editor de texto fuera de línea y también llamado editor de flujo, el sed.

Por ultimo trataremos de ver las características de un lenguaje de programación que hace mucho mas que editar texto, el awk.


7.1:Edición de textos en modo interactivo


7.1.1¿Porque es importante el uso de editores de consola?


Muy bien, se cuenta ya con poderosos programas de edición como los mencionados anteriormente y uno se siente tan cómodo como cundo trabajaba en otro tipo de entorno de ventanas (Bill, ¿esta alli?), pero que ocurre cuando queremos hacer funcionar ese monstruo consumidor de recursos en un 486 DX2 con 8 MB. No puede funcionar de ninguna manera, ni siquiera X podría hacerlo de un modo que nos facilite las tareas.

Otro ejemplo, salimos de nuestra maquina perfectamente equipada y vamos a configurar otra maquina no tan bien equipada, no podemos dejar de hacer el trabajo porque no tiene interfaz gráfica o no tiene el Star Office 5.1.

Por esto es importante el saber usar este tipo de editores, ya que estarán en cualquier sistema GNU/Linux, por lo menos el vi, y que necesitan de muy pocos recursos o muchos menos que X para funcionar.

El entender este tipo de programas nos abren las puertas para poder configurar y trabajar con cualquier computadora que posea un sistema tipo UNIX ya que han sido portados a tanto vi como emacs a la mayoría de las plataformas dada su funcionalidad.


Si se les presenta caso que alguna vez se tenga que editar algún archivo a través Internet en una maquina remota agradecerán por mucho la capacidad del editor vi y su velocidad, dado que es poco el contenido que tendrá que pasarse por la conexión y por ende se tendrá mucha mas soltura a la hora de trabajar con un archivo y en los tiempos de respuesta que el editor tendrá

Por supuesto que se tendrá que tener en cuenta el gusto personal por cada uno de los editores que pasaremos a explicar, pero de seguro se contara con la suficiente información para poder hacer una elección de acuerdo a las conveniencias de cada usuario.

Para poder ejemplificar algunos de los puntos fuertes de cada uno de estos editores, podríamos decir que vi es el editor de textos garantizado en todos los equipos con GNU/Linux y UNIX. Aunque no es él más fácil de usar, a esta altura se tendrá la experiencia suficiente para armarse de paciencia y obtener el máximo beneficio de él.

El editor de textos Emacs es pesado pero muy poderoso. Posee hasta un dialecto del lenguaje de programación LISP además de diversas extensiones avanzadas como el Eliza que es un programa para tareas de Inteligencia Artificial.


7.1.2: El editor vi


Al verlo por primera vez la gente tiene recuerdos de los primeros editores de textos de DOS, toscos y faltos de muchas características, pero una vez que se a aprendido a usarlo se encuentra uno ubicado en el sector de la gente que piensa que en verdad es un programa mágico.

No es un programa muy difícil de usar, aunque parezca lo contrario en principio, es solo que el aprendizaje inicial suele costar mucho dado que no se contaran con menues descolgables o clic de mouse para ejecutar una función del programa y ni siquiera esta en colores en muchos casos.

Para ir viendo algunas características que el vi posee y a modo de que vayan entrando en el sector de gentes antes mencionado, veremos características en este editor que lo ponen como uno de los más completos.


Pero tendremos que ver algunos conceptos fundamentales antes de poder hacer esto.

Mientras se este usando el editor vi se estará en uno de tres posibles modos de operación.

Estos modos son:

  1. Modo Comando

  2. Modo de Inserción

  3. Modo de Ultima Línea


VI puede ser iniciado tanto llamándolo sin argumentos, con lo que se tendrá que establecer un nombre a la hora de salir del programa, o con un nombre de archivo, con lo cual si el archivo existe lo abrirá y si no existe lo creara.

La sintaxis es la siguiente:


[sebas@LUSI]$vi <archivo>


Donde archivo es el nombre del archivo a editar o crear. EN caso que no se ponga ningún archivo, se preguntara el nombre de este cuando queramos guardar o cuando salgamos del programa.

Al iniciarse, lo hará en modo comando por lo que no se podrá ingresar texto directamente. Para pasar al modo de inserción, se cuenta con un comando "i" (INSERT) o "a" (ADD).

En ese momento nos encontraremos con la posibilidad de escribir el contenido del archivo a crear o a editar. Para volver al modo de comandos vasta solo con oprimir la tecla (ESC).

El modo ultima línea sirve para proporcionar al "vi" ciertos comandos extendidos que aparecerán en la ultima línea de la pantalla, de aquí su nombre. Por ejemplo, supongamos que quisiéramos salir del archivo que estamos editando sin tener que gravar, para ello presionando ":" dos puntos y luego "q!" el vi saldrá sin guardar ningún cambio. Por supuesto que en el modo ultima línea se tiene que presionar la tecla "ENTER" después del comando.

Para entender un poco estos conceptos trataremos de ejemplificar un poco el proceso de edición, mostrando como se editaría un archivo nuevo.

Para esto crearemos un archivo llamado "prueba":


[sebas@LUSI]$vi prueba


Dado que el archivo no existe, este se creara lo que se nos indicara al final de la pantalla con la línea siguiente.


prueba: new file: line 1


Lo que mostrara el editor vi al comenzar es una pantalla donde en la 1º columna se verán repetidos símbolos de tilde "~", esto indica que donde esta el primero de estos tildes finaliza el archivo y que luego no hay nada más.

En estos momentos estamos en modo de comandos, por lo que necesitaremos para comenzar a trabajar ingresar el comando (i) lo que nos hará entrar al modo de inserción para así comenzar a escribir.

A la hora de tener que agregar contenido podrá también pasar al modo de inserción a través de la letra "a" (ADD). La diferencia con el comando (i) es que con el comando (a) se comenzara a escribir después del cursor en cambio con el (i) esto se hará antes del cursor.

Si el universo fuese un programa estaría hecho en C y correría sobre un sistema Unix.

Anónimo.

~

~

~

~

~

~

~

~

~



Como en otro editores de textos se podrá seguir escribiendo líneas sucesivas solo con oprimir la tecla "ENTER" la que generara un "EOL (End of line)"

Si existiese un error lo podremos corregir primero borrando el carácter con error (tecla x sobre el carácter a borrar en modo comando) y luego insertando el correcto (i). Pero podremos por ejemplo reemplazar directamente el carácter con error directamente con el comando (r) REPLACE.

Pero que pasa si existiesen varios caracteres seguidos que quisiéramos corregir. Pondremos entonces el comando REPLACE pero con la letra "r" mayúscula (R) lo que nos permitirá seguir reemplazando caracteres hasta presionar la tecla (ESC) para volver al modo comando.




Para moverse por el texto puede hacerse directamente con las teclas de cursor que nos llevará al lugar donde esta el problema.


Para reemplazar esta palabra lo que hicimos fue posicionarnos con el cursor encima de la letra "á" y en modo comando presionar la tecla (i), y así insertamos la letra "í".

Si lo que quisiéramos es comenzar a escribir una nueva línea en blanco, lo lograremos presionando la tecla (o) en modo comando.




Ya dijimos que para borrar algún carácter en especial tendremos que posicionar el cursor encima de este y, en modo comando, presionar la tecla (x). Pero si lo quisiéramos seria borrar una palabra de 5 letras, lo que tendríamos que hacer es presionar "x" 5 veces.

Pero esto no es del todo practico así que si queremos borrar una palabra completa bastara con posicionarnos con el cursor en ella y presionar "dw" (DELETE WORD) en modo comando con lo que la palabra será borrada.

Si lo que quisiéramos es borrar una línea completa tendremos que presionar 2 veces la tecla d "dd" en modo comando encima de la línea a borrar.





Las modificaciones que le podemos hacer al texto las vimos anteriormente con el comando "R" y "r", pero también podremos hacer otro tipo de modificación como el cambiar el texto a mayúscula.

Para esto contamos con el comando "~".




Para poder mover el cursor de un lado a otro también se cuenta con 4 teclas que pueden resultar un poco más cómodas al este en modo comando.

Estas son h,j,k,l que nos permitirán mover el cursor a la izquierda, abajo, arriba y a la derecha.




Con la tecla "w" el cursor se moverá al comienzo de cada palabra y con la tecla "b" se ira al comienzo de la palabra anterior:


Con la orden 0 (cero) nos podremos mover al comienzo de la línea actual y con el "$" al final de la línea actual.

En ocasiones el texto que tenemos que editar es por demás de extenso y por ello tendremos que encontrar un método mejor para ir moviéndonos a través de este.

Dado que no contamos con una barra de desplazamiento que nos permita poder movernos por el documento tendremos que usar los métodos convencionales de conjunto de comandos.

Para ello tenemos que pulsando Crtl - F se avanzara el cursor una pantalla hacia delante y con Ctrl.-B lo llevaremos una pantalla hacia atrás.

Si lo que queremos es llegar al final del documento tenemos el comando G y si lo que en realidad se necesitaba es el llegar a una línea determinada tendremos que anteponer al comando "G" el numero de la línea a la que queremos ir. Por ejemplo si quisiéramos llegar a la línea 25 del documento teclearíamos, por supuesto en modo comando, 25G y el cursor parpadeara debajo de la primer letra de esa línea.


Muy bien, el trabajo esta hecho y se necesita ahora guardarlo. Para esto tendremos que darle una orden desde el modo ultima línea. Para ello primero ingresaremos ":" los dos puntos, que nos llevara al modo ultima línea y seguido esto teclearemos la letra w (WRITE) y presionaremos ENTER (:w), con esto el documento será guardado, y en caso de que no hallásemos dado un nombre todavía, es decir que hayamos arrancado el vi sin ningún nombre como parámetro, se guardara en un archivo temporal el cual nos indicara.

Para darle un nombre, lo tendremos que indicar inmediatamente después de haber puesto los dos puntos y la letra "w". (:w archivo), de esta forma ahora cada vez que se ingrese el comando "w" desde el modo ultima línea, se guardara el documento en el nombre de archivo que indicamos.

Si lo que quisiéramos es guardar y salir la forma de indicárselo es a través del comando "qw" (:wq) que guardara el archivo y saldrá del programa. Claro esta que si no indicamos un nombre se tendrá que proceder de igual forma que el caso anterior.

Podremos hacer lo mismo desde el modo comando presionando dos veces la tecla Z mayúscula (ZZ). Para salir sin guardar existen dos formas de acuerdo a lo que se haya hecho.

Si no se modifico el documento, bastara que desde el modo ultimo línea se presione la tecla "q" seguido de ENTER.(:q)

Si se modifico el documento, entonces deberemos forzar la salida con ayuda del símbolo "!" de esta forma (:q!).


Lo formidable que tiene este editor de texto en modo consola que otros no tienen, es la posibilidad de editar ficheros múltiples. Esto permite que podamos editar algún otro archivo con solo indicárselo. De esta forma será más rápido que salir del "vi" y arrancarlo con otro nombre de archivo como parámetro.

Para esto bastara solo con ingresar ":e" seguido del nombre del archivo a editar.

Si el archivo que actualmente estamos editando no a sido guardado nos lo indicara para que no perdamos los cambios.

Si queremos en realidad incluir el contenido de otro archivo, tenemos la orden :r. La forma de emplearlo es (:r archivo) y de esta forma todo el contenido de ese archivo será incluido en el documento que estamos editando actualmente.

Existe una utilidad muy interesante del vi que nos permite ejecutar comandos del bash directamente y que los resultados se incorporen al texto que estamos editando.

Si el universo fuese un programa estaría hecho en C y correría sobre un sistema Unix.

Anónimo.

total 9

-rwx--x--x 1 sebas sebas 192 May 21 13:00 case

-rwx--x--x 1 sebas sebas 203 May 21 12:43 case2

-rwx--x--x 1 sebas sebas 218 May 21 12:48 caso

-rw-rw-r-- 1 sebas sebas 20 Jun 7 18:54 loco

-rwx--x--x 1 sebas sebas 120 May 16 09:14 miscrip

-rw-rw-r-- 1 sebas sebas 96 Jun 6 08:12 prueba

-rwxrwxr-x 1 sebas sebas 87 May 21 11:42 scrip

-rwxrwxr-x 1 sebas sebas 374 May 21 11:45 script

-rw-rw-r-- 1 sebas sebas 275 Jun 1 06:46 test

~

~

~


Con la misma orden :r! y seguido el comando que queremos ejecutar, el comando será ejecutado y el resultado será incluido en el documento.


Claro esta que se puede salir del interprete de comandos y ejecutar la orden directamente y una vez finalizada volver al editor vi.

Esto se logra con el símbolo "!":

Por ejemplo:


:! ls -l


También podremos salir temporalmente del vi regresar al interprete de comandos.

Para esto deberemos indicárselo con el comando :shell.

Luego una vez que terminemos de usar el interprete de comandos, podremos poner "exit" y regresaremos al vi.


Una utilidad interesante es la de repetir el ultimo comando que se ejecuto. Para esto tenemos el comando punto "." que desde el modo comando nos permitirá repetir cualquier comando que hayamos ejecutado anteriormente.

Por ejemplo si lo que hicimos antes fue el borrar una palabra con el comando "dw", si presionamos el punto "." será igual que hubiésemos tecleado "dw" otra vez. Esto funciona con la mayoría de los comando que podamos ejecutar desde el modo comando.


Si quisiéramos buscar una palabra en especial dentro del texto, bastara solo con presionar la el comando "/" lo que nos ubicará en la ultima línea para que ingresemos la cadena de texto a encontrar. Vi comenzara a buscar desde el punto donde se encuentre el cursor hasta el final del texto y cada vez que encuentra una coincidencia nos lo indicara poniendo el cursor debajo de esta. Si queremos seguir buscando, bastara con presionar la tecla "n" (NEXT) para que encuentre la próxima coincidencia.

Muchas veces tendremos que reemplazar sucesivamente una palabra en el texto y tendremos que buscarlo una por una y reemplazarlo a mano.

Vi cuenta con un método que puede ser útil usando la diagonal "/" y luego la cadena que estamos buscado.

Ahora bien, una vez que la encontramos solo tendremos que presionar "cw" lo que nos permitirá corregir la cadena, reemplazamos la cadena que encontramos con la que queremos y luego repetimos la búsqueda presionando (ESC) que nos pondrá en modo comando y presionando la tecla "n" que nos llevara a la próxima coincidencia. En este punto en lugar de repetir lo anterior solo bastara con presionar el comando "." que repetirá el reemplazo efectuado anteriormente y así presionando "n" y "." sucesivamente podremos reemplazar todas las coincidencias.

Claro esta que no es esto muy útil si se quiere reemplazar 100 coincidencias por lo que podremos hacerlo de una sola vez indicando en cuantas líneas se podrá encontrar esta cadena.

Para ello se ingresan los ":" dos puntos seguido de la primera de las líneas en la que tenemos la palabra a cambiar, seguido una coma y luego la ultima línea a cambiar. Luego pondremos el comando a usar "s" para sustituir, una diagonal, la palabra a buscar otra diagonal y la palabra con la que será reemplazada.


Ej:


:1, 200s/sebas/SEBAS


Claro que esto solo cambiara la primer aparición en la línea, si existiera otra en la misma línea seria ignorada. Para que el alcance sea total se deberá agregar el comando g (GLOBAL) al final del comando.


:1, 200s/sebas/SEBAS/g


Ahora bien si se quiere que vi nos pregunte antes de cambiar se deberá agregar el comando "c" al final, que nos pregunte si se quiere realizar el cambio antes de cada una de las coincidencias:


:1, 200s/sebas/SEBAS/gc


Para todo esto deberemos saber cuantas líneas tiene el documento, lo que podemos hacer es indicarle que lo haga desde donde nosotros queramos hasta el final del documento con la ayuda del símbolo "$".


:1,$s/sebas/SEBAS/gc


Si se quiere realizar en todo el documento, podremos directamente indicarlo con el símbolo "%" que es igual a "1,$".


:%s/sebas/SEBAS/gc


Por supuesto que los patrones de búsqueda que usamos podrán ser expresiones regulares, que facilitaran mucho el trabajo.


Si quisiéramos que se reemplace no importa si esta escrito en mayúscula o minúscula se podrá poner algo como esto:


:%s/[Ss][Ee][Bb][Aa][Ss]/nanci/gc


Este uso de las expresiones regulares también puede incluir el uso de metacaracteres como el "*" para indicar cualquier cantidad de caracteres anterior o "." para cualquier carácter individual:


:%s/*[Bb].[Ss]/nanci/gc


Pero si se a hecho algo mal, no preocuparse ya que "vi" cuenta con un comando de "undo" el cual por supuesto se activa con el comando "u".


Existen muchísimos temas que se han dejado de ver aquí, por lo que se invita al lector a buscar en la documentación del vi que lo guiara a toda la magia que este editor tiene para brindar.


7.1.3 Editor Emacs



En cuanto a poder se refiere Emacs gana por varios cuerpos a sus competidores.

Este desarrollo totalmente GNU a sabido cubrir el terreno de la edición de textos de alto nivel en los sistemas UNIX por muchos años, y sigue siendo un ejemplo del poder real que se puede obtener de este tipo de sistemas.

Por supuesto, es un editor más poderoso que el pequeño "vi" y por ende la curva de aprendizaje es mucho mayor.

Pero si lo que se quiere es tener mas que un simple editor de textos y acercarse a lo que una suite de aplicaciones puede dar, Emacs es el lugar donde se tiene que buscar.

Y es así de simple, no solo nos encontraremos con un fabuloso editor de textos, sino que tendremos una completa suite de aplicaciones de uso común, tales como edición, recepción y envió de mails, programación en C, edición de HTML y SGML, programación en de macros en lenguaje LISP, corrección ortográfica en varios idiomas y muchas características mas.


Existe una diferencia en la forma de trabajar con respecto a vi, en lugar de tener que cambiar de modo para poder trabajar con una u otra función, modo comando, modo ultima línea y demás, emacs responde de acuerdo a la función que la conjunción de teclas presionada tenga.

Este es el mismo comportamiento que poseen otros editores de textos como el Star Office o el Word y por lo tanto se tendrán que saber las combinaciones posibles para poder trabajar cómodamente.

Al arrancar emacs puede hacerlo de dos formas distintas dependiendo en el ambiente donde se este trabajando.

Si se esta trabajando en modo texto, emacs arrancara con lo que se denomina entorno de pantalla completa, es decir se llena toda la pantalla. Si se ejecuta emacs en el entorno X, este lo entenderá y arrancará la versión de X en lugar de la de texto.




Versión X de Emacs


Por supuesto que si se quiere ejecutar la versión de texto en un entorno como X uno puede hacerlo, para ello basta con ejecutar emacs con los modificadores -nw (NO WINDOWS).


Ej:

emacs -nw


Ahora bien, si lo ejecutamos con un nombre de archivo como argumento resultara de la misma forma que con el editor vi, si el archivo existe se abrirá para ser editado, si no se creara uno nuevo.

En el entorno grafico se podrá contar con una serie de menús desplegables al igual que otros programas de X y así será mas fácil llegar a las opciones, y por ello solo trataremos de ver las opciones que se tienen, no todas, para ser usadas en un entorno de texto y luego podrán ser empleadas ya conociendo su funcionamiento en cualquiera de los dos entornos.

Para poder usar los menú en modo texto, si presionamos la tecla F10 tendremos bajo la pantalla de edición los nombres de cada uno de los menús y al elegirlos y presionar ENTER entraremos en su contenido y en las diversas ordenes que tienen.

Con F1 entraremos al modo de ayuda donde tendremos una reseña de los comandos de Emcas




Ventana de ayuda



Para salir de este cuadro bastara con presionar 3 veces la tecla ESC (ESC ESC ESC).

Al comenzar, emacs esta en lo que se denomina modo "fundamental" que es uno de los modos en los que puede encontrarse dependiendo del tipo de trabajo que se esta haciendo, determinando esto el comportamiento básico del programa.

Los otros modos sirven para efectuar las distintas tareas antes mencionadas como el leer correo, la edición de HTML y compilación de lenguaje C.


La forma de saber en que modo se encuentra, es leyendo la línea de estado:

Para movernos dentro del documento tenemos as facilidades de las teclas de cursor o bien diciéndole hacia donde tiene que ir el curso mediante un comando.

Por ejemplo si quisiera ir hacia adelante palabra a palabra teclearíamos Esc-f (f de fordward) y nos iremos moviendo de esa manera. A modo inverso teclearemos Esc-b para ir hacia atrás.

Para moverse hacia arriba y hacia abajo podremos hacerlo por medio de Ctrl-v para ir una pantalla adelante y Esc-v para ir una pantalla hacia atrás. Solo se tendrá que recordar que para ingresar un comando que comienza con la tecla shift, antes deberemos presionar la tecla ESC.

A continuación mostraremos una tabla básica de movimientos para emacs.


Carácter

Acción

Ctrl-b

Se mueve hacia atrás un carácter

Ctrl-f

Se mueve hacia adelante un carácter

Esc-b

Se mueve hacia atrás una palabra

Esc-f

Se mueve hacia adelante una palabra

Ctrl-p

Se mueve a la línea anterior

Ctrl-n

Se mueve a la línea siguiente

Ctrl-a

Se mueve al inicio de la línea

Ctrl-e

Se mueve al final de la línea

Ctrl.-v

Se mueve hacia adelante una pantalla

Esc-v

Se mueve hacia atrás una pantalla

Esc->

Se mueve al final del buffer (archivo)

Esc-<

Se mueve al inicia del buffer (archivo)


La edición de texto es muy completa, permitiendo marcar un fragmento del texto para copiarlo o cortarlo para pegarlo en otro lugar del documento.

El texto cortado o copiado permanece en un buffer del procesador de texto y no tiene que ser único. Por ende podríamos tener varios fragmentos de texto en él y podrimos pegar cualquiera de ellos.

La diferencia con otros editores de texto esta en que el proceso de pegar el contenido del portapapeles se denomina "yanking" (jalar).

La siguiente tabla muestra los comando para edición mas comunes.


Carácter

Acción

Ctrl-d

Borra el carácter que esta bajo el cursor

Del

Borra el carácter anterior

Esc-Del

Borra la palabra anterior

Esc-d

Borra la palabra sobre la que esta el cursor

Ctrl-k

Borra la línea

Ctrl-w

Borra región marcada

Esc-w

Copia región marcada

Ctrl-y

jala (inserta) texto del cortapapeles

Ctrl-@ o Ctrl-Espacio

Asigna el inicio de una región.


Como en el procesador de textos "vi", tendremos la posibilidad de buscar un texto determinado, pero de una forma un poco mas cómoda, ya que emacs incorpora lo que se denomina búsqueda incremental (I-search).

Este tipo de búsqueda de ira haciendo en tiempo real a medida que vayamos poniendo caracteres luego de presionar Ctrl-s, lo que inicia la búsqueda, buscando una concordancia.

Bajo la línea inferior aparecerá una referencia de esta forma


I-search:


A medida que pongamos caracteres los iremos viendo luego de esa línea:


I-search: o


Y en el texto el cursor se ira desplazando a la primer palabra que comience con "o".

Así a medida que se ingresen caracteres, emacs nos llevara hacia la primer palabra que concuerde.

Si al terminar de escribir la palabra, todavía no se a llegado a la región donde se quería, bastara con teclear nuevamente Ctrl-s y emacs buscara la próxima ocurrencia de la palabra buscada anteriormente.


Por supuesto la búsqueda es mas útil si se la puede usar para reemplazar algún texto en el documento, y esto es posible en emacs a través del comando shift-% con lo que se pedirá primero el texto a buscar y luego el texto por el que será reemplazado.

A continuación mostraremos una tabla que muestra las posibilidades de búsqueda y reemplazo que emacs posee.


Carácter

Acción

Ctrl-s

Busca hacia adelante en forma incremental

Ctrl-r

Busca hacia atrás en forma incremental

Esc o .

Termina la búsqueda

espacio o Y

Reemplaza la cadena preguntando antes de hacerlo

Ctrl-g

Cancela la búsqueda y regresa al inicio

Del

Para borrar un carácter incorrecto en la cadena de búsqueda

Esc-%

Se ingresa la cadena a buscar y el reemplazo

Shift-x

Cambia todas la ocurrencias del documento


Existe muchas funciones mas y queda para el lector si es de su interés el estudio del lenguaje incorporado LISP par la generación de funciones y macros que serán de mucha ayuda para usar este editor.



7.2 Conceptos de editores fuera de línea


Existen ocasiones en las que el uso de un editor de textos como el vi o emacs puede ser demasiado o no cumplen con lo que queremos realizar.

Tal vez se tengan que hacer cambios repetitivos a archivos o tener que procesar datos de una fuente y enviarlos a otro archivo en un orden correcto o tal ves solo queremos una forma simple de hacer el trabajo desde un script o la línea de comandos.

Es aquí donde entran a trabajar los editores fuera de línea y para nombrar solo 2 veremos el editor de flujo "sed" y el lenguaje de programación "awk" (por Alfred Aho,Peter Weinberg y Brian Kernighan).

Lo especial de awk es que es un lenguaje con todas las letras y muy poderoso, pero en ocasiones nos facilitara tareas tediosas de procesamiento de información y por esto lo ponemos en el rango de un editor fuera de línea. Aunque esto no quiere decir que es lo único que puede hacer.

Para mayor información sobre sed y awk les sugiero lean "Sed & AWK" de Dale Dougherty que trata el tema con una mayor profundidad.


7.2.1: Sed


No es preciso detallar en demasía el uso de este editor fuera de línea dada que posee mucha similitud en su uso al editor de textos vi pero si es bueno mostrar algunas de sus funciones y usos tanto en el procesamiento desde un script o en la línea de comandos.


Existen 3 casos específicos en los que se podrá usar Sed.

  1. Para editar archivos muy largos para editar interactivamente.

  2. Para editar archivos de cualquier tamaño cuando la secuencia de comandos

de edición es muy complicada para hacer el tipeado confortable en ambiente interactivo.

  1. Para usar múltiples funciones globales de edición eficientemente e un

solo paso.


Existen diferentes formas de realizar una edición con el Sed. Puede hacerse desde la línea de comando o simplemente guardándolos en un archivo para poder ser usado luego.

Sed lee la entrada línea a línea y realiza los cambios a estas de acuerdo a lo que se le especifique. Luego de hacer estos cambios dirige su salida hacia stdout, por supuesto que esto lo podemos cambiar.

Sed actúa en forma similar a filtros como el grep y sort pero con la diferencia que con sed se podrán crear programas mas complicados y con una mayor cantidad de funciones.

Para definir una estructura de uso del sed veremos 2 formas distintas.

La primera es la utilizada en la línea de comandos a través de una canalización y que tendrá esta estructura:


primer_comando | sed <opciones> <descripción_de_la_edición>


A continuación veremos la segunda opción para su uso a partir de la línea de comandos:


sed -f script_de_edición <archivo>


Con la opción "-f" le decimos a sed que a continuación le pasaremos un archivo donde encontrara las reglas a aplicar en <archivo>.

Sed tiene mucho que ver con el editor vi en el área de búsqueda y reemplazo donde la estructura es la siguiente:


[direccion1][,direccion2]] descripción_de_la_edición [argumentos]


Las direcciones serán reglas que el sed tendrá que encontrar en el texto, si se omitieran estas sed realizara en caso de ser posible los cambios en forma global.

La descripción_de_la_edición indica a sed los cambios que tiene que hacer. Para esto, tema que veremos a continuación, pueden usarce varios argumentos.

Es posible hacer varios cambios a una línea, sed los realiza de a uno y cuando ya no haya mas cambios a realizar en una línea dada, sed enviara el resultado a la salida estándar.

Sed posee un contador interno de líneas que se va incrementando de acuerdo al numero total de líneas leídas y no a las líneas del archivo. Por esto si se editan dos archivos juntos de 50 líneas cada uno, la línea numero 60 de sed seria la línea 10 del segundo archivo. Esto es bueno para tener en cuenta a la hora de realizar ediciones a múltiples archivos.

Como dijimos antes cada comando de sed puede tener 0, 1, o2 direcciones y en caso de tener 0, se aplicara a todas las líneas de ser posible:




/seba/s/entrada/salida/


El comando "s" indica a sed que debe hacer una sustitución de los argumentos que son pasados.

Este simple comando, que puede estar en un archivo guardado para ser pasado al sed, sustituye la primera aparición de "salida" por "entrada" en las líneas que contengan "seba".

Cuando se ingresan dos direcciones, el cambio se comenzara a efectuar en la línea que concuerde la primer dirección y se ira aplicando a todas las siguientes hasta que concuerde con la segunda dirección. Las dos direcciones se separan con coma. Por ejemplo:


10,30s/entrada/salida/


Sed aquí una sustitución de "salida" por "entrada" a partir de la línea nº 10 hasta la línea nº 30.

Obsérvese que no tiene que existir ningún espacio entre el comando "s" y la segunda dirección.

Si las direcciones tiene al final un signo "!" (negado) el comando solo se aplicar a aquellas líneas que no concuerden con la dirección dada. Por ejemplo.


10,30!s/entrada/salida/


Este comando se aplicara a todas la líneas, menos a las que estén entre la numero 10 y la 30 inclusive.


Como antes dijimos podremos modificar la salida del sed. Por ejemplo si quisiéramos mostrar por la salida estándar las líneas de una archivo que están entre la 20 y la 40, podremos dar a sed los argumentos necesarios:


[sebas@LUSI]$cat archivo | sed -n '20,40p'


El -n indica a sed que imprima solo las líneas que concuerden con los argumentos pasados, dado que evita que se impriman todos los demás. El comando "p" es para imprimir el patrón que encuentra sed.

Ya estamos en condiciones de hacer un script rudimentario para imprimir líneas de archivos:


[sebas@LUSI]$ find /home/sebas/cartas/* -print | while read FILE

>do

>echo $FILE

>cat $FILE | sed -n '5,15p'

>done


A continuación se mostrara por la salida estándar desde la línea 5 hasta la 15 inclusive de todos los archivos del directorio /home/sebas/cartas.


Existen veces que queremos tener partes de archivos que concuerden con un patrón determinado, por ejemplo, si quisiéramos mandar todos los comentarios de un archivo de shell_script a otro y sabemos que las líneas que lo son comienzan con "#" podemos usar un comando en sed que haga el trabajo por nosotros de forma muy simple.


[sebas@LUSI]$cat archivo | sed -n '/^#/w archivo2'


Debe existir un espacio exacto entre la "w" y el "archivo2" Con el -n indicamos a sed que solo procese las líneas que concuerdan con la dirección que le pasaremos.

Con el símbolo "^" le decimos a sed que tiene que encontrar la dirección al principio de la línea. Y con la w le indicamos que escriba la salida al archivo2.

A continuación pondremos una tabla de los comando que se usan en sed.

Se recomiendan que practiquen con ellos y que observen los resultados obtenidos.


Carácter

Acción

a

añade texto al espacio patrón

b

ramifica a un rotulo, se emplea de forma similar a un go to

c

añade texto

d

borra texto

i

inserta texto

l

lista el contenido del espacio patrón

n

añade una nueva línea al espacio patrón

p

imprime el espacio patrón

r

lee un archivo

s

sustituye patrones

w

escribe a un archivo


7.2.2: AWK


EL awk es un poderoso lenguaje de programación que en muchas ocasiones nos sacara de apuros a la hora de tener que hacer script complejos de tratamiento de texto.

El awk al igual que el sed lee las líneas completas para realizar sus modificaciones.

Uno de los aspectos mas útiles en relación al awk es que a diferencia del "sed",awk puede dividir las líneas en campos a través de un separador de campo indicado en el script o en la línea de comandos.

Si no se indica ninguno se tomara como separador de campo un espacio o tabulador.

Usando la opción -F de la línea de comandos o la variable FS desde un programa hecho en awk se puede especificar un nuevo separador de campo.

Por ejemplo si lo que quisiéramos es ver los nombres verdaderos que aparecen en el archivo /etc/passwd primero tendríamos que saber como separar los campos. En el archivo /etc/passwd se separan por un ":". Ahora tendríamos que saber en que campo se encuentra el nombre. Es en el campo numero 5, comenzando a contar como el primero de los campos. El 0 es la línea completa y ya veremos por que.


[sebas@LUSI]$ cat /etc/passwd | awk -F : '{print $5}'

root

bin

daemon

adm

lp

sync

shutdown

halt

mail

news

uucp

operator

games

gopher

FTP User

Nobody

X Font Server

Named

PostgreSQL Server

Sebastián D. Criado

[sebas@LUSI]$


Como vemos lo primero que hicimos fue indicarle al awk cual seria el separador de campo "-F :", luego entre comillas le indicamos que imprima a la salida estándar el campo nº 5, '{print $5}'.

De esta forma vemos los nombres contenidos en el archivo /etc/passwd.

Podríamos imprimir mas de un campo a la vez, por ejemplo si queremos mostrar también el directorio home de cada uno de los usuarios podríamos hacer lo siguiente:


[sebas@LUSI]$ cat /etc/passwd | awk -F : '{print $5,$6}'

root /root

bin /bin

daemon /sbin

adm /var/adm

lp /var/spool/lpd

.

.

.

PostgreSQL Server /var/lib/pgsql

Sebastián D. Criado /home/sebas

[sebas@LUSI]$


De esta simple manera podremos ir completando la línea a los requerimientos del campo que queramos ver ya que tenemos la posibilidad de hacer comparaciones a un campo de la misma manera que la haríamos a una variable en cualquier otro lenguaje.

Por ejemplo si quisiéramos ver las líneas del /etc/passwd de todos aquellos usuarios que pertenecen al grupo user, representado por el nº 100 en el archivo passwd, podríamos hacer que el awk comprara el numero del campo en el que esta el numero GUID que nosotros buscamos.

En el caso particular que cada usuario tuviese su grupo, podrimos hacer que se compararan todas las líneas que posean un numero mayor o igual al numero de grupo de usuarios mas bajo, por ejemplo 500 es el numero que por defecto pone Red Hat a al grupo del primer usuario y va incrementándose a medida que incorporamos usuarios. Tendríamos que mostrar todas las líneas que en campo donde esta el GUID, el numero 4, del usuario y que sea mayor o igual a 500.


Por ejemplo:


[sebas@LUSI]$ cat /etc/passwd | awk -F : '$4>=500 {print $0}'

sebas:x:500:500:Sebastián D. Criado:/home/sebas:/bin/bash

nanci:x:501:501:Nanci Funes:/home/nanci:/bin/bash

[sebas@LUSI]$


Como verán se indico que mostrara solo aquellas líneas que tuviesen en el campo nº 4 un valor mayor o igual a 500, $4>=500.También se ve que mostramos la línea entera al poner como campo a imprimir el $0.

Una acotación que tendríamos que notar. Lo que comparamos en esta oportunidad es un numero y esto lo hace tremendamente poderoso al awk como lenguaje de programación. Si se quisieran compara cadenas, se tendrían que encerrar ente "".

Como ejemplo, si hubiésemos encerrado entre "" al 500 lo que awk interpretaría es que queremos mostrar todas las líneas que en la posición 4 tengan un valor alfabéticamente mayor o igual al "500".


Ejemplo:





[sebas@LUSI]$ cat /etc/passwd | awk -F : '$4>="500" {print $0}'

lp:x:4:7:lp:/var/spool/lpd:

nobody:x:99:99:Nobody:/:

sebas:x:500:500:Sebastián D. Criado:/home/sebas:/bin/bash

nanci:x:501:501:Nanci Funes:/home/nanci:/bin/bash

sebas@LUSI]$


Como veran si se ordena alfaveticamente la posicion 4 el 7 y el 99 son mayores que 500.


Los operadores que awk puede manejar son los siguientes:


Operador

Significado

<

menor que

<=

menor que o igual

= =

igual a

!=

no igual a

>=

mayor que o igual a

>

mayor que


Otra posibilidad es el usar expresiones regulares para efectuar la búsqueda.

Pero cuidado ya que es tienen que ser ingresadas de acuerdo a si es mayúscula o minúscula.


[sebas@LUSI]$ cat /etc/passwd | awk -F : '/Sebas/ {print $0}'

sebas:x:500:500:Sebastián D. Criado:/home/sebas:/bin/bash

[sebas@LUSI]$


Lo único que tendremos que hacer es encerrarlo entre "/" para que se tomen como expresión regular.

Ahora bien, las expresiones podrán ser tan complejas como queramos. Por ejemplo si quisiéramos mostrar todas las líneas que tuviesen la cadena "se" pero que no tengan antes la letra "U" y no les siga un espacio la orden seria así.


[sebas@LUSI]$ cat /etc/passwd | awk -F : '/[^U]se[^ ]/ {print $0}'

sebas:x:500:500:Sebastián D. Criado:/home/sebas:/bin/bash

[sebas@LUSI]$


Como ven las cadenas que tenemos que ignorar se preceden antes y después de la cadena buscada ingresando un símbolo ^ encerrado entre [].

De esta manera se podrá ir usando las distintas expresiones regulares.


En todos estos casos se utilizaron una única forma para imprimir en pantalla los resultados, pero es bueno saber que contamos con otra forma en la que podremos formatear el texto antes de su salida por pantalla.

Para la salida formateada se utiliza el "printf".

Por ejemplo si quisiéramos podrimos imprimir los datos en una forma mas cómoda:


[sebas@LUSI]$ cat /etc/passwd | awk -F : '$4>=500 {printf"%20s %5s\n",$5,$1}'

Sebastián D. Criado sebas

Nanci Funes nanci

[sebas@LUSI]$



Como se puede ver, pedimos que nos mostrara el nombre completo de l usuario y el nombre de usuario. Como sabemos la extensión aproximada que tendrá cada campo le damos 20 posiciones para le primer campo a mostrar, el $5, y 5 posiciones para el segundo campo a mostrar, el $1.

Si lo que quisiéramos mostrar fuesen numero en lugar de la "%s" (string) iría una "%d" o "%i" (decimal).Para mas información sobre el printf buscar en las paginas de manual del awk.


Existen diferentes variables integradas, a parte del FS, que permiten llevar cuentas de de distintos aspectos.

Por ejemplo existe la variable NR que llevara la cuenta de los registros que mostremos.

Por ejemplo supongamos que necesitamos obtener un listado largo de un directorio, pero solo queremos ver los permisos, el nombre del archivo y el numero de registro que a pasado por el awk.


sebas@LUSI]$ ls -l | awk '{ print NR" "$1" "$9}'

1 total

2 -rw-rw-r-- 146768

3 -rw-rw-r-- Bienvenidos

4 -rw-rw-r-- Bienv

5 -rw-rw-r-- authkey.file

6 drwxr-xr-x Desktop

7 -rw-rw-r-- LUGRo

8 drwxrwxr-x Linux

9 -rw-rw-r-- Listado

10 -rw-rw-r-- Lo

11 drwx------ Mail

.

.

.

49 -rw-rw-r-- pgaccess-report.ps

50 -rw-rw-r-- sed

51 -rw-rw-r-- sed.zip

52 -rw-rw-r-- smtptel.htm

53 -rw-rw-r-- vicky


Como verán, en esta ocasión la variable NR fue llevando la cuenta de los registros que fueron pasando por el awk.

De esta forma se podrá decirle al awk que me muestre de los registros 5 al 10 solamente.


[sebas@LUGRO]$ ls -l | awk 'NR>=5 && NR<=10 { print NR" "$1" "$9}'

5 -rw-rw-r-- Bienvenidos

6 drwxr-xr-x Desktop

7 -rw-rw-r-- LUGRo

8 drwxrwxr-x Linux

9 -rw-rw-r-- Listado

10 -rw-rw-r-- Lo

[sebas@LUSI]$


Existen muchas mas variables en el awk que son de extrema utilidad.

Por ejemplo, en el caso anterior sabíamos que el ultimo campo estaba en la posición numero 9, pero ¿que ocurre si no sabemos la posición del ultimo campo o esta varia?

Para esto esta la variable NF que lleva la cuenta de la cantidad de campos de cada registro.

Por ello en lugar de la anterior forma podrimos poner:



[sebas@LUSI]$ls -l | awk '{ print NR" "$1" "$NF}'


y obtendrimos identicos resultados.

Pero un momento, aqui hay algo raro. La variable NR no tiene el signo $, en cambio la variable NF si lo tiene.

Esto esta dado así para que no se reemplazado por el awk. Por ejemplo si hubiésemos puesto la variable NF sin signo $ el resultado seria.


[sebas@LUSI]$ ls -l | awk '{ print NR" "$1" "NF}'

1 total 2

2 -rw-rw-r-- 9

3 -rw-rw-r-- 11

4 -rw-rw-r-- 11

5 -rw-rw-r-- 11

6 drwxr-xr-x 9

.

.

.


Lo que nos esta mostrando no es el ultimo campo, sino la cantidad de campos que ese registro tiene. Al agregarle el signo $ se reemplazara con el numero del ultimo campo y ese campo el que será mostrado. Esto es así para todas las variables integradas.


El awk puede ser usado no-solo en una línea. Podrimos usarlo también como cualquier otro lenguaje para realizar múltiples tareas en una línea o realizar algo antes de comenzar la lectura y otra después.

Para demarcar el código se utiliza los pares BEGIN-END. Todo lo que aparece después de la palabra BEGIN, pero en el mismo renglón, se realiza antes de que comience el ciclo. Cualquier cosa que este después de END se realiza después de que se haya leído la ultima línea y cerrado el ciclo. Estas líneas tendrán que estar en un archivo que será utilizado por el awk para procesar en este ejemplo al archivo /et/passwd.


Un ejemplo seria el siguiente:


BEGIN { FS=":"}

{ printf"Nombre Completo: %s\n",$5 }

{ printf"Nombre de Usuario: %s\n",$1}

{ printf"UID: %i,GUID: %i\n\n",$3,$4 }

END { printf "\n\nTotal de usuarios: %d \n\n", NR}


Este pequeño programa realizado con el vi será guardado en el archivo awk.src, el nombre se lo damos nosotros, y nos servirá para mostrar algunos datos del /etc/passwd mas detalladamente.

La forma de ejecutarlo es a través de el modificado "-f" donde le decimos al awk que a continuación le pasaremos un archivo con el programa que tiene que usar para procesar el /etc/passwd.


[sebas@LUSI]$ awk -f awk.src /etc/passwd Nombre Completo: root

Nombre de Usuario: root

UID: 0,GUID: 0


Nombre Completo: bin

Nombre de Usuario: bin

UID: 1,GUID: 1


Nombre Completo: daemon

Nombre de Usuario: daemon

UID: 2,GUID: 2


Nombre Completo: adm

Nombre de Usuario: adm

UID: 3,GUID: 4

.

.

.

Nombre Completo: PostgreSQL Server

Nombre de Usuario: postgres

UID: 26,GUID: 26


Nombre Completo: Sebastián D. Criado

Nombre de Usuario: sebas

UID: 500,GUID: 500


Nombre Completo: Nanci Funes

Nombre de Usuario: nanci

UID: 501,GUID: 501


Total de usuarios: 22


Para finalizar diremos que también se podrán hacer operaciones con estas variables, es decir, sumarlas restarlas, multiplicarlas y dividirlas. Por ejemplo si quisiéramos saber en cuantos bloques de 4 líneas podríamos

formar con un archivo de texto dado podríamos hacer el siguiente programa:


BEGIN {FS=":"}

{ print $0 }

FNR%4==0 { printf"\n" }

END { printf"El archivo %s puede entrar en %i bloques enteros de 4 lineas\n",FILENAME,NR/4}



Existen un par de cosas nueva en el. Por ejemplo la variable "FNR" que cuenta el numero de líneas. En esta ocacion le estamos diciendo que si el modulo de FNR es igual a 4 "FNR%4" imprima un salto de linea "{ printf"\n" }".

Y al finalizar el ciclo se mostrara el mensaje que nos informara cuantos bloques de 4 líneas podremos tener. Para obtener el resultado se efectúa una división del numero total de registros "NR" por el numero de líneas que queremos armar el bloque, "4". La variable FILENAME indica cual es el archivo sobre el cual se realizo el proceso y es tomada cuando se la pasamos al awk como argumento.


El resultado es el siguiente:



sebas@LUSI]$ awk -f awk2.src /etc/passwd

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:

daemon:x:2:2:daemon:/sbin:

adm:x:3:4:adm:/var/adm:


lp:x:4:7:lp:/var/spool/lpd:

sync:x:5:0:sync:/sbin:/bin/sync

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

halt:x:7:0:halt:/sbin:/sbin/halt


mail:x:8:12:mail:/var/spool/mail:

news:x:9:13:news:/var/spool/news:

uucp:x:10:14:uucp:/var/spool/uucp:

operator:x:11:0:operator:/root:


games:x:12:100:games:/usr/games:

gopher:x:13:30:gopher:/usr/lib/gopher-data:

ftp:x:14:50:FTP User:/home/ftp:

nobody:x:99:99:Nobody:/:


xfs:x:43:43:X Font Server:/etc/X11/fs:/bin/false

named:x:25:25:Named:/var/named:/bin/false

gdm:x:42:42::/home/gdm:/bin/bash

postgres:x:26:26:PostgreSQL Server:/var/lib/pgsql:/bin/bash


sebas:x:500:500:Sebastián D. Criado:/home/sebas:/bin/bash

nanci:x:501:501:Nanci Funes :/home/nanci:/bin/bash


El archivo /etc/passwd puede entrar en 5 bloques enteros de 4 lineas



Sebastián D. Criado - www.lugro.org.ar

seba_AT_lugro.org.ar