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 VIII- Hola amigo, como estás?
- Muy bien!, quería mostrarte lo que hice, pero ya sé que tu quieres ir rápido a lo que interesa, no?
- Solo para llevarte la contraria, hoy voy a dejar que me muestres tu "programita". Venga, muéstrame lo que hiciste.
- Ahhh ... el ejercicio que me pasaste es muy extenso. Yo lo resolví así: $ cat musinc5
#!/bin/bash
# Registra CDs (versión 5)
#
clear
LineaMesg=$((`tput lines` - 3)) # Linea que define cuantos mensajes serán pasados de una vez a la pantalla
TotCols=$(tput cols) # Cantidad de columnas de la pantalla para encuadrar mensajes
echo "
Inclusión de Músicas
========= == =======
Título del Álbum:
| Este campo fue
Pista: < creado solamente para
| orientar como llenar
Nombre de la Música:
Intérprete:" # Pantalla montada con un único echo
while true
do
tput cup 5 38; tput el # Posiciona y limpia linea
read Albun
[ ! "$Albun" ] && # Operador pulso <ENTER>
{
Msg="Desea Terminar? (S/n)"
TamMsg=${#Msg}
Col=$(((TotCols - TamMsg) / 2)) # Centra mensaje en la linea
tput cup $LineaMesg $Col
echo "$Msg"
tput cup $LineaMesg $((Col + TamMsg + 1))
read -n1 SN
tput cup $LineaMesg $Col; tput el # Borra mensaje de la pantalla
[ $SN = "N" -o $SN = "n" ] && continue # $SN es igual a N o (-o) n?
clear; exit # Fin de la ejecución
}
grep "^$Albun\^" musicas > /dev/null &&
{
Msg="Este álbum ya está incluido"
TamMsg=${#Msg}
Col=$(((TotCols - TamMsg) / 2)) # Centra mensaje en la linea
tput cup $LineaMesg $Col
echo "$Msg"
read -n1
tput cup $LineaMesg $Col; tput el # Borra mensaje de la pantalla
continue # Vuelve para leer otro álbum
}
Reg="$Albun^" # $Reg recibirá los datos para grabación
elArtista= # Variable que graba artista anterior
while true
do
((Track++))
tput cup 7 38
echo $Track
tput cup 9 38 # Posiciona para leer música
read Musica
[ "$Musica" ] || # Si el operador escribio
- Si, el programa esta bien, esta todo bien estructurado, pero me gustaría comentarte un poco lo que hiciste:
Funciones
- Mozo! Ahora tráeme dos "chops" bien helados, uno sin espuma, para que me de inspiración. Pregunta () { # La función recibe 3 parámetros en el siguiente orden: # $1 - Mensaje que será mostrado en la pantalla # $2 - Valor que será aceptado como respuesta por defecto # $3 - Otro valor aceptado # Suponiendo que $1=Acepta?, $2=s y $3=n, la linea a # seguir colocaría en Msg el valor "Acepta? (S/n)" local Msg="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)" local TamMsg=${#Msg} local Col=$(((TotCols - TamMsg) / 2)) # Centra mensaje en la linea tput cup $LineaMesg $Col echo "$Msg" tput cup $LineaMesg $((Col + TamMsg + 1)) read -n1 SN [ ! $SN ] && SN=$2 # Si esta vacía coloca por defecto en SN echo $SN | tr A-Z a-z # La salida de SN será en minúscula tput cup $LineaMesg $Col; tput el # Borra mensaje de la pantalla return # Sale de la función }
Como podemos ver, una función es definida cuando hacemos
Fíjate que las variables
La linea de código que crea
Casi al final de la rutina, la respuesta recibida ( Veamos ahora como quedaría la función para presentar un mensaje en la pantalla: function MandaMsg { # La función recibe solamente un parámetro # con el mensaje que se desea mostrar, # para no obligar al programador que pase # el mensaje entre comillas, usaremos $* (todos # los parámetros, te acuerdas?) y no $1. local Msg="$*" local TamMsg=${#Msg} local Col=$(((TotCols - TamMsg) / 2)) # Centra el mensaje en la linea tput cup $LineaMesg $Col echo "$Msg" read -n1 tput cup $LineaMesg $Col; tput el # Borra el mensaje de la pantalla return # Sale de la función }
Esta es otra forma de definir una función: no la llamamos como en el ejemplo anterior usando una construcción con la sintaxis Para terminar con este blá-blá-blá vamos a ver entonces las alteraciones que el programa necesita cuando usamos el concepto de funciones: $ cat musinc6
#!/bin/bash
# Registra CDs (versión 6)
#
# Área de las variables globales LineaMesg=$((`tput lines` - 3)) # Linea que mensajes serán dados para el operador TotCols=$(tput cols) # Cantidad de columnas de la pantalla para encuadrar mensajes # Área de las funciones Pregunta () { # La función recibe 3 parámetros en el siguiente orden: # $1 - Mensaje que será mostrado en la pantalla # $2 - Valor que será aceptado como respuesta default # $3 - Otro valor aceptado # Suponiendo que $1=Acepta?, $2=s y $3=n, la linea a # seguir colocaría en Msg el valor "Acepta? (S/n)" local Msg="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)" local TamMsg=${#Msg} local Col=$(((TotCols - TamMsg) / 2)) # Centra mensaje en la linea tput cup $LineaMesg $Col echo "$Msg" tput cup $LineaMesg $((Col + TamMsg + 1)) read -n1 SN [ ! $SN ] && SN=$2 # Si vacia coloca default en SN echo $SN | tr A-Z a-z # La salida de SN será en minúscula tput cup $LineaMesg $Col; tput el # Borra mensaje de la pantalla return # Sale de la función } function MandaMsg { # La función recibe solamente un parametro # con el mensaje que se desea mostrar, # para no obligar al programador que pase # el mensaje entre comillas, usaremos $* (todos # los parametros, te acuerdas?) y no $1. local Msg="$*" local TamMsg=${#Msg} local Col=$(((TotCols - TamMsg) / 2)) # Centra mensaje en la linea tput cup $LineaMesg $Col echo "$Msg" read -n1 tput cup $LineaMesg $Col; tput el # Borra mensaje de la pantalla return # Sale de la función }
# El cuerpo del programa propiamente dicho comienza aqui
clear
echo "
Inclusión de Músicas
========= == =======
Título del Álbun:
| Este campo fue
Pista: < creado solamente para
| orientar como llenar
Nombre de la Música:
Intérprete:" # Pantalla montada con un único echo
while true
do
tput cup 5 38; tput el # Posiciona y limpia linea
read Albun
[ ! "$Albun" ] && # Operador dió Fijate que la estructura del _script_esta como en el gráfico de abajo:
Esta estructuración es debida a que el Shell es un lenguaje interpretado y así el programa es leído de izquierda a derecha y de arriba para abajo. De esa forma, para que una variable sea vista simultáneamente por el script y sus funciones, debe ser declarada (o inicializada) antes de cualquier otra cosa. Las funciones deben ser declaradas antes del cuerpo del programa propiamente dicho para que en el lugar en que el programador mencione su nombre, el interprete Shell ya lo haya localizado antes y registrado que es una función.
Una cosa muy útil en el uso de funciones es tratar de hacerlas lo más generales posible, de forma que sirvan para otras aplicaciones, sin necesidad de tener que reescribirlas. Esas dos que acabamos de ver tienen uso general, pues es dificil hallar un script que tenga una entrada de datos por teclado que no use una rutina del tipo de la Consejo de amigo: crea un archivo y cada función nueva que programes, añádela a este archivo. Así con el tiempo tendrás una bella biblioteca de funciones que te ahorrará mucho tiempo de programación. El comando source
Fíjate si notas algo diferente en la salida del $ ls -la .bash_profile
-rw-r--r-- 1 Julio unknown 4511 Mar 18 17:45 .bash_profile
No mires la respuesta y vuelve a prestar atención! De acuerdo, ya que no tienes paciencia para pensar y prefieres leer la respuesta, te voy a dar una pista: me parece que ya sabes que el .bash_profile es uno de los programas que son automáticamente "ejecutados" cuando tu te logeas (ARRGGHH! Odio este término). Ahora que te dí esta ayuda, mira nuevamente la salida del Como te dije el .bash_profile es "ejecutado" en el momento del logon y fíjate que no tiene ningúna prerrogativa de ejecución. Esto ocurre porque si tu lo ejecutaras como cualquier otro script simple, cuando terminara su ejecución, todo el ambiente generado por él moriría junto con el Shell en el cual fue ejecutado (te acuerdas que todos los scripts son ejecutados en subshells, verdad?).
Pues bien, es para cosas así que existe el comando
Mejor un ejemplo que 10.000 palabras. Mira el $ cat script_bobo
cd ..
ls
Simplemente debería ir hacia el directório superior del directório actual. Vamos a ejecutar unos comandos que incluyen el script_bobo y vamos a analizar los resultados: $ pwd
/home/jneves
$ script_bobo
jneves juliana paula silvie
$ pwd
/home/jneves
Si yo mandé subir un directório, porque no subió? Subió sí! El subshell que fue creado para ejecutar el script subió y listó los directórios de los cuatro usuarios debajo del $ source script_bobo
jneves juliana paula silvie
$ pwd
/home
$ cd -
/home/jneves
$ . script_bobo
jneves juliana paula silvie
$ pwd
/home
Ahh! Ahora sí! Siendo pasado como parámetro del comando
Y ahora debes estarte preguntando, sólo sirve para eso este comando?, y yo te digo que sí, pero eso nos trae una cantidad de ventajas y una de las más usadas es tratar funciones como rutinas externas. Mira una forma diferente de hacer nuestro programa para incluir CDs en el archivo $ cat musinc7
#!/bin/bash
# Registra CDs (versión7)
#
# Área de varibles globales LinhaMesg=$((`tput lines` - 3)) # Línea que msgs serán dadas para operador TotCols=$(tput cols) # Qtd colunas de la tela para encuadrar msgs
# El cuerpo del programa propriamente dicho comienza aqui
clear
echo "
Inclusión de Músicas
======== == =======
Título do Álbum:
| Este campo fue
Pista: < creado solamente para
| orientar como llenar
Nombre de la Música:
Intérprete:" # Pantalla montada con un único echo
while true
do
tput cup 5 38; tput el # Posiciona y limpa línea
read Album
[ ! "$Album" ] && # Operador dió
Ahora el programa disminuyo considerablemente de tamaño y las funciones fueron cambiadas por archivos externos llamados
Por motivos meramente didácticos las ejecuciones de Mira ahora como quedaron estos dos archivos: $ cat pergunta.func
# La función recibe 3 parámetros en el siguiente orden:
# $1 - Mensaje a ser enviado a la pantalla
# $2 - Valor que sera aceptado como respuesta por defecto
# $3 - El otro valor aceptado
# Suponiendo que $1=Acepta?, $2=s y $3=n, en la línea
# de abajo colocaría en Msg el valor "Acepta? (s/n)"
Msg="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)"
TamMsg=${#Msg}
Col=$(((TotCols - TamMsg) / 2)) # Centra msg en la línea
tput cup $LinhaMesg $Col
echo "$Msg"
tput cup $LinhaMesg $((Col + TamMsg + 1))
read -n1 SN
[ ! $SN ] && SN=$2 # Si esta vacía coloca default en SN
echo $SN | tr A-Z a-z # La salida de SN será en minúscula
tput cup $LinhaMesg $Col; tput el # Borra msg de la pantalla
$ cat mandamsg.func
# La función recibe solamente un parámetro
# con el mensaje que se desea exhibir,
# para no obligar al programador a pasar
# el msg entre comillas, usaremos $* (todos
# los parámetro, recuerdas?) y no $1.
Msg="$*"
TamMsg=${#Msg}
Col=$(((TotCols - TamMsg) / 2)) # Centra msg en la línea
tput cup $LinhaMesg $Col
echo "$Msg"
read -n1
tput cup $LinhaMesg $Col; tput el # Borra msg de la pantalla
En ambos archivos, hice solamente dos cambios que veremos en las observaciones que siguen, sin embargo tengo tres observaciones más para hacer:
- Bien, ahora ya tienes una cantidad de novedades para mejorar los scripts que hicimos. Te acuerdas del programa $ cat listartista
#!/bin/bash
# Dado un artista, muestra sus músicas
# versión 2
if [ $# -eq 0 ] then echo Usted debería haber pasado al menos un parámetro exit 1 fi IFS=" :" for ArtMus in $(cut -f2 -d^ musicas) do echo "$ArtMus" | grep -i "^$*~" > /dev/null && echo $ArtMus | cut -f2 -d~ done
- Claro que me acuerdo!...
- Entonces para afirmar los conceptos que te pasé, hazlo con la pantalla formateada, en loop, de forma que solamente termine cuando reciba un
- Mozo, trae dos más, el mio con poca presión... 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ém 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 - 10 Jan 2007 -- PatricioReich - 24 Nov 2006 |
|||
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. |