Programación del Shell LinuxAquí tenemos un libro libre y completo sobre ShellLa sed del "conocimiento libre" es muy bienvenida. |
Comandos Shell Script |
![]() |
|
Home |
Artículos ![]() ![]() |
Comprar el libroChangelogs |
|
Conversación de Bar - Parte VII- Como dijiste? Repite que no te entiendo! Se te derritieron los pensamientos para hacer el
- Si, realmente tuve que colocar mucha materia gris en la pantalla, pero creo que lo conseguí! Bueno, por lo menos en los tests que hice la cosa funcionó, pero tu siempre me colocas piedras en el camino!
- No sera tanto, programar en shell es muy fácil, lo que vale son los consejos y los detalles de programación que te doy, que no son triviales. Las correcciones que te hago, son justamente para mostrarlos. Pero vamos a pedir dos "chopps" y le echo una ojeada a tu script.
- Mozo, trae dos. No te olvides que uno es sin espuma! $ cat restaura
#!/bin/bash
#
# Restaura archivos borrados vía erreeme
#
if [ $# -eq 0 ]
then
echo "Uso: $0
- Un momento, déjame ver se lo entendí. Primero colocas en la variable Dir la última línea del archivo cuyo nombre está formado por /tmp/nombre del operador ($LOGNAME)/parámetro pasado con el nombre del archivo a ser restaurado ($1). Enseguida el grep -v que montaste borra esa línea en que estaba el nombre del directorio, o sea, siempre es la última y manda lo que resta del archivo, que sería el archivo ya limpio, hacia el directorio original para después borrar el archivo del "cubo de la basura"; S E N S A C I O N A L! Impecable! Ningun error! Lo viste? ya le estás tomando las medidas al shell!
- Entonces vamos a continuar, basta ya de bla-bla-bla, de que vas a hablar hoy?
- Ah! estoy viendo que el bichito del Shell se te contagió. Que bueno, vamos a ver como se pueden (y deben) leer datos y formatear pantallas, pero primero vamos a conocer un comando que te da todas las herramientas para que formatees tu pantalla de entrada de datos. El comando tputEste comando se usa principalmente para posicionar el cursor en la pantalla, sin embargo también es muy usado para borrar datos de la pantalla, saber la cantidad de líneas y columnas de la pantalla, posicionar correctamente un campo, borrar un campo cuya entrada se detectó como error. En fin, casi toda la formatación de la pantalla es hecha por este comando.
Unos pocos atributos del comando En la tabla siguiente, se presentan los principales atributos del comando y los efectos ejecutados sobre la pantalla, pero debes saber que existen muchos más que esos, mira sino:
$ tput it
8
Este ejemplo devolvió el tamaño inicial del <TAB> ( Initial T ab), y dime una cosa: para que quiero saber eso? Si quieres saber todo sobre el comando tput (y mira que es de nunca acabar), vea a: http://www.cs.utah.edu/dept/old/texinfo/tput/tput.html#SEC4.
Vamos a hacer un programa bien sencillo para mostrar algunos atributos de este comando. Es el famoso usado y abusado Hola Mundo, sólo que esta frase será escrita en el centro de la pantalla y en vídeo inverso y después de eso, el cursor volverá hasta la posición en que estaba antes de escribir esta frase tan creativa. Observa: $ cat hola.sh
#!/bin/bash
# Script bobo para testar
# el comando tput (versión 1)
Columnas=`tput cols` # Grabando cantidad columnas Líneas=`tput lines` # Grabando cantidad líneas Línea=$((Líneas / 2)) # Cual es la línea del medio de la pantalla? Columna=$(((Columnas - 11) / 2)) # Centrando el mensaje en la pantalla tput sc # Grabando posición del cursor tput cup $Línea $Columna # Posicionándose para escribir tput rev # Vídeo inverso echo Hola Mundo! tput sgr0 # Restaura el vídeo a normal tput rc # Restaura el cursor a la posición original
Como el programa ya está todo comentado, creo que la única explicación necesaria sería para la línea en que es creada la variable De esta forma, este programa solamente conseguiría centrar cadenas de 11 caracteres, sin embargo, mira esto: $ var=Conversa
$ echo ${#var}
8
$ var="Conversa de Bar"
$ echo ${#var}
15
Ahhh, mejoró! Entonces ahora sabemos que la construcción $ cat hola.sh
#!/bin/bash
# Script bobo para testar
# el comando tput (versión 2)
Columnas=`tput cols` # Grabando cantidad columnas Líneas=`tput lines` # Grabando cantidad líneas Línea=$((Líneas / 2)) # Cual es la línea del medio de la pantalla? Columna=$(((Columnas - ${#1}) / 2)) #Centrando el mensaje en la pantalla put sc # Grabando posición del cursor tput cup $Línea $Columna # Posicionándose para escribir tput rev # Vídeo inverso echo $1 tput sgr0 # Restaura vídeo a normal tput rc # Restaura cursor en la posición original
Este script es igual al anterior, sólo que cambiamos el valor fijo de la versión anterior ( Columna=`$(((Columnas - ${#*}) / 2))` #Centrando el mensaje en la pantalla
y la línea Y ahora podemos leer los dados de la pantallaBien, a partir de ahora vamos a aprender todo sobre lectura, solo que no te puedo enseñar a leer las cartas o el futuro, porque sino ya seria rico, estaria en un pub de Londres, tomando scotch y no en un bar tomando "chopp". Pero vamos a continuar.
La última vez que nos encontramos aquí ya te dí una introducción sobre el comando $ read var1 var2 var3
Conversa de Bar
$ echo $var1
Conversa
$ echo $var2
de
$ echo $var3
Bar
$ read var1 var2
Conversa de Bar
$ echo $var1
Conversa
$ echo $var2
de Bar
Como viste, el
Yo mencioné una lista separada por espacios en blanco? Pero ahora que ya lo conoces todo sobre el $ oIFS="$IFS"
$ IFS=:
$ read var1 var2 var3
Conversa de Bar
$ echo $var1
Conversa de Bar
$ echo $var2
$ echo $var3 $ read var1 var2 var3 Conversa:de:Bar $ echo $var1 Conversa $ echo $var2 de $ echo $var3 Bar $ IFS="$oIFS"
Te diste cuenta, estaba equivocado! La verdad es que el $ grep julio /etc/passwd
julio:x:500:544:Julio C. Neves - 7070:/home/julio:/bin/bash
$ oIFS="$IFS" # Grabando IFS
$ IFS=:
$ grep julio /etc/passwd | read lname lixo uid gid coment home shell
$ echo -e "$lname\n$uid\n$gid\n$coment\n$home\n$shell"
julio
500
544
Julio C. Neves - 7070
/home/julio
/bin/bash
$ IFS="$oIFS" # Restaurando IFS
Como viste, la salda del
En el Bash existen diversas opciones del
Y ahora directo a los ejemplos cortos para demostrar estas opciones. Para leer un campo "Matrícula": $ echo -n "Matricula: "; read Mat # -n no salta línea
Matricula: 12345
$ echo $Mat
12345
O simplificando con la opción $ read -p "Matricula: " Mat
Matricula: 12345
$ echo $Mat
12345
Para leer una determinada cantidad de caracteres: $ read -n5 -p"CEP: " Num ; read -n3 -p- Compl
CEP: 12345-678$
$ echo $Num
12345
$ echo $Compl
678
En este ejemplo hicimos dos Para leer hasta que un determinado tiempo termine (conocido como time out): $ read -t2 -p "Digite su nombre completo: " Nom || echo 'Ah perezoso!'
Escriba su nombre completo: JAh perezoso!
$ echo $Nom
$
Obviamente esto fue una broma, ya que solo tenía 3 segundos para escribir mi nombre completo y sólo me dio tiempo de teclear una
Para leer un dato sin ser mostrado en la pantalla: $ read -sp "Seña: "
Seña: $ echo $REPLY
secreto :)
Aprovecho un error para mostrarte un detalle de programación. Cuando escribi la primera línea, me olvidé de colocar el nombre de la variable que iría a recibir la contraseña, y sólo noté eso cuando fui a listar su valor. Por suerte la variable
Pero el ejemplo que dí, era para mostrar que la opción Bien, ahora que sabemos leer de la pantalla, veamos como se leen los datos de los archivos. Vamos a leer archivos?
Como ya te habia dicho y te debes de acordar, el
1 - Redireccionando la entrada del archivo hacia el bloque del while read Línea do echo $Línea done < archivo
2 - Redireccionando la salida de un cat archivo | while read Línea do echo $Línea done Cada uno de los procesos tiene sus ventajas y desventajas: Ventajas del primer proceso:
Desventaja del primer proceso:
Ventaja del segundo proceso:
Desventajas del segundo proceso:
$ cat readpipe.sh
#!/bin/bash
# readpipe.sh
# Ejemplo de read pasando archivo por pipe.
Ultimo="(vacío)" cat $0 | # Pasando el arch. del script ($0) p/ while while read Línea do Ultimo="$Línea" echo "-$Ultimo-" done echo "Acabó, Último=:$Ultimo:" Vamos a ver su ejecución: $ readpipe.sh
-#!/bin/bash-
-# readpipe.sh-
-# Ejemplo de read pasando archivo por pipe.-
--
-Ultimo="(vacío)"-
-cat $0 | # Pasando el arch. del script ($0) p/ while-
-while read Línea-
-do-
-Ultimo="$Línea"-
-echo "-$Ultimo-"-
-done-
-echo "Acabó, Último=:$Ultimo:"-
Acabó, Último=:(vacío):
Como viste, el script lista todas sus própias líneas con un signo de menos (
- Será que la variable no fue actualizada?
- Lo fue, y eso puede ser comprobado porque la línea
- Entonces que paso?
- Pues que como ya te dije, el bloque de instrucciones redireccionado por el pipe ( $ cat redirread.sh
#!/bin/bash
# redirread.sh
# Ejemplo de read pasando archivo por redireccionamento de entrada (<).
Ultimo="(vacío)" while read Línea do Ultimo="$Línea" echo "-$Ultimo-" done < $0 # Pasando el arch. del script ($0) p/ while echo "Acabó, Último=:$Ultimo:" Y mira su ejecución sin errores: $ redirread.sh
-#!/bin/bash-
-# redirread.sh-
-# Ejemplo de read pasando archivo por redireccionamento de entrada (<).-
--
-Ultimo="(vacío)"-
-while read Línea-
-do-
-Ultimo="$Línea"-
-echo "-$Ultimo-"-
-done < $0 # Pasando el arch. del script ($0) p/ while-
-echo "Acabó, Último=:$Ultimo:"-
Acabó, Último=:echo "Acabó, Último=:$Ultimo:":
Bien amigos de la Red Shell, para finalizar el comando $ seq 30 > numeros
$ cat 10porpag.sh
#!/bin/bash
# Prg de test para escribir
# 10 líneas y parar para leer
# Versión 1
while read Num do let ContLin++ # Contando... echo -n "$Num " # -n para no saltar línea ((ContLin % 10)) > /dev/null || read done < numeros
Como forma de hacer un programa genérico creamos la variable $ 10porpag.sh
1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 21 23 24 25 26 27 28 29 30
Fíjate que falta el número Vamos a mostrar entonces como debería quedar para funcionar correctamente: $ cat 10porpag.sh
#!/bin/bash
# Prg de test para escribir
# 10 líneas y parar para leer
# Versión 2
while read Num do let ContLin++ # Contando... echo -n "$Num " # -n para no saltar línea ((ContLin % 10)) > /dev/null || read < /dev/tty done < numeros
Observa que ahora la entrada del Observa ahora su ejecución: $ 10porpag.sh
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
Esto está casi bien, pero falta un poco para quedar excelente. Vamos a mejorar un poco el ejemplo para que lo reproduzcas y verifiques (pero antes de verificar, aumenta el número de registros de $ cat 10porpag.sh
#!/bin/bash
# Prg de test para escribir
# 10 líneas y parar para leer
# Versión 3
clear while read Num do ((ContLin++)) # Contando... echo "$Num" ((ContLin % (`tput lines` - 3))) || { read -n1 -p"Teclee Algo " < /dev/tty # para leer cualquier caracter clear # limpia la pantalla despues de la lectura } done < numeros
El cambio principal hecho en este ejemplo, es con relación al salto de página, ya que esta hecho en cada cantidad-de-líneas-de-pantalla (
- Bien amigo mio, por hoy ya basta porque me parece que estás saturado de esto...
- No, no lo estoy, realmente puede continuar...
- Si tu no lo estás, yo sí... Pero ya que estás tan entusiasmado con el Shell, te voy a dejar un ejercicio de aprendizaje que mejorara tu CDteca y que es bastante simple. Reescribe tu programa que registra CDs para montar toda la pantalla con un único Y no te olvides, cualquer duda o falta de compañia para tomar una cerveza o hasta para hablar mal de los políticos lo único que tienes que hacer es mandarme un e-mail para julio.neves@gmail.com. Voy aprovechar también para mandar mi aviso publicitario: puedes decirle a los amigos que quien quiera hacer un curso nota diez de programación en Shell que mande un e-mail para julio.neves@uniriotec.br para informarse. Gracias y hasta la próxima -- HumbertoPina - 17 Jan 2007 |
||||||||||||||||||||||||||||||||||||||||||||||||||
Licencia Creative Commons - Reconocimiento y no comercial (CC) 2009 Por Visitantes del Bar de Júlio Neves. Todo el contenido de esta página puede ser usada de acuerdo a la Creative Commons License: Atribuição-UsoNãoComercial-PermanênciaDaLicença. |