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 IX- Está bien, ya sé que vas a querer un "chopp" antes de empezar, pero tengo muchas ganas de enseñarte primero lo que hice, así que voy pidiéndote ya la bebida y enseguida te lo muestro.
- Mozo!, trae dos. El de él sin espuma para no ensuciarse el bigote...
- Mientras el "chopp" no llega, déjame recordarte que me pediste que rehiciera el
- Primero optimize el $ cat mandamsj.func
# La función recibe solamente un parámetro
# con el mensaje que se desea exhibir.
# Para no obligar al programador a pasar
# el msj entre comillas, usaremos $* (todos
# los parámetros, recuerdas?) y no $1.
Msj="$*"
TamMsj=${#Msj}
Col=$(((TotCols - TamMsj) / 2)) # Centra msj en la línea
tput cup $líneaMesj $Col
read -n1 -p "$Msj "
$ cat pregunta.func
# La función recibe 3 parámetros en el siguiente orden:
# $1 - mensaje a ser dado en pantalla
# $2 - Valor a ser acepto como respuesta default
# $3 - El otro valor aceptado
# Suponiendo que $1=Acepta?, $2=s y $3=n, la línea
# abajo colocaría en Msj el valor "Acepta? (s/n)"
Msj="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)"
TamMsj=${#Msj}
Col=$(((TotCols - TamMsj) / 2)) # Centra msj en la línea
tput cup $líneaMesj $Col
read -n1 -p "$Msj " SN
[ ! $SN ] && SN=$2 # Si vacía coloca default en SN
SN=$(echo $SN | tr A-Z a-z) # La salida de SN será en minúscula
tput cup $líneaMesj $Col; tput el # Borra msj de la pantalla
- Y aquí va el grandullón ahora: $ cat listartista3
#!/bin/bash
# Dado un artista, muestra sus músicas
# versión 3
líneaMesj=$((`tput lines` - 3)) # línea que msjs serán dados al operador TotCols=$(tput cols) # Ctd de columnas de la pantalla para encuadre de msjs clear echo " +----------------------------------------------------+ | Lista Todas las Músicas de un Determinado Artista | | ----- ----- -- ------- -- -- ----------- ------- | | | | Informe el Artista: | +----------------------------------------------------+" while true do tput cup 5 51; tput ech 31 # ech=Erase chars (31 caracteres para no borrar barra vertical) read Nombre if [ ! "$Nombre" ] # $Nombre está vacío? then . pregunta.func "Desea Salir?" s n [ $SN = n ] && continue break fi fgrep -iq "^$Nombre~" musicas || # fgrep no interpreta ^ como expresión regular { . mandamsjg.func "No existe música de este artista" continue } tput cup 7 29; echo '| |' LinActual=8 IFS=" :" for ArtMus in $(cut -f2 -d^ musicas) # Excluye nombre del album do if echo "$ArtMus" | grep -iq "^$Nombre~" then tput cup $LinActual 29 echo -n '| ' echo $ArtMus | cut -f2 -d~ tput cup $LinActual 82 echo '|' let LinActual++ if [ $LinActual -eq $líneaMesj ] then . mandamsj.func "Teclee Algo para Continuar..." tput cup 7 0; tput ed # Borra la pantalla a partir de la línea 7 tput cup 7 29; echo '| |' LinActual=8 fi fi done tput cup $LinActual 29; echo '| |' tput cup $((++LinActual)) 29 read -n1 -p "+-----------Teclee Algo para Nueva Consulta----------+" tput cup 7 0; tput ed # Borra la pantalla a partir de la línea 7 done
- Caramba!, hoy llegaste con mucha fuerza! Pero me gustó la forma en que resolviste el problema y estructuraste el programa. Fue más trabajoso pero la presentación quedó excelente y usaste bastante las opciones del +----------------------------------------------------+ | Lista Todas las Músicas de un Determinado Artista | | ----- ----- -- ------- -- -- ----------- ------- | | | | Informe el Artista: Emerson, Lake & Palmer | +----------------------------------------------------+ | | | Jerusalem | | Toccata | | Still ... You Turn Me On | | Benny The Bouncer | | Karn Evil 9 | | | +-----------Teclee Algo para Nueva Consulta----------+ Mejorando la escritura- Ufa! Ahora ya lo sabes todo sobre lectura, pero sobre escritura apenas estás gateando. Ya sé que me vas a preguntar: - Pero, no era con el comando
Si, con estos comandos escribes el 90% de las cosas necesarias, sin embargo, si necesitas escribir algo formateado te dará mucho trabajo. Para formatear la salida veremos ahora una instrucción muy interesante - el printf formato [argumento...]
En donde:
Argumento - es la cadena a ser impresa con el control del formato .
Cada uno de los caracteres utilizados para especificación de
Las secuencias de escape patrón del lenguaje C son siempre precedidas por una barra invertida (
Y no se acaba aquí, todavía hay más! Hay muchas más cosas sobre esta instrucción, pero como son muchos detalles es por consiguiente aburrido de explicar y todavía peor de leer o estudiar, así que vamos directos a los ejemplos con sus comentarios, que no estoy aqui para aburrir a nadie. $ printf "%c" "1 caracter"
1$ Error! Sólo listó 1 caracter y no saltó de línea al final
$ printf "%c\n" "1 caracter"
1 Saltó de línea pero todavia no listó la cadena entera
$ printf "%c caracteres\n" 1
1 caracter Esta es la forma correcta, el %c recebió el 1
$ a=2
$ printf "%c caracteres\n" $a
2 caracteres O %c recibió el valor de la variable $a
$ printf "%10c caracteres\n" $a
2 caracteres
$ printf "%10c\n" $a caracteres
2
c
Observa que en los dos últimos ejemplos, en virtud del Y aqui vá un ejemplo:
$ printf "%d\n" 32
32
$ printf "%10d\n" 32
32 Rellena con blancos a la izquierda y con ceros
$ printf "%04d\n" 32
0032 04 despues % significa 4 dígitos con ceros a la izquierda
$ printf "%e\n" $(echo "scale=2 ; 100/6" | bc)
1.666000e+01 El default del %e es 6 decimales
$ printf "%.2e\n" `echo "scale=2 ; 100/6" | bc`
1.67e+01 El .2 especificó dos decimales
$ printf "%f\n" 32.3
32.300000 El default del %f es 6 decimales
$ printf "%.2f\n" 32.3
32.30 El .2 especificó dos decimales
$ printf "%.3f\n" `echo "scale=2 ; 100/6" | bc`
33.330 El bc devolvió 2 decimales. El printf colocó 0 a la derecha
$ printf "%o\n" 10
12 Convirtió el 10 en octal
$ printf "%03o\n" 27
033 Así la conversión queda con más apariencia de octal, sí?
$ printf "%s\n" Palabra
Palabra
$ printf "%15s\n" Palabra
Palabra Palabra con 15 caracteres rellenados con blancos
$ printf "%-15sNeves\n" Palabra
Palabra Neves El menos (-) rellenó a la derecha con blancos
$ printf "%.3s\n" Palabra
Pal 3 Corta y deja sólo las 3 primeras
$ printf "%10.3sa\n" Peteleca
Peta Pet con 10 caracteres concatenado con a (después del s)
$ printf "EJEMPLO %x\n" 45232
EJEMPLO b0b0 Transformó en hexa pero los zeros no combinan
$ printf "EJEMPLO %X\n" 45232
EJEMPLO B0B0 Así quedó mejor (Fíjate en la X mayúscula)
$ printf "%X %XL%X\n" 49354 192 10
C0CA C0LA
El último ejemplo no es marketing y es bastante completo, voy a comentarlo paso a paso:
Como puedes notar, la instrucción
Creo que cuando me decidí a explicar el Principales Variables del ShellEl Bash posee diversas variables que sirven para dar informaciones sobre el ambiente o alterarlo. Su número es muy grande y no pretendo mostrártelas todas sino una pequeña parte, y que pueden ayudarte en la elaboración de scripts. Ahí van las principales:
$ echo $CDPATH
.:..:~:/usr/local
$ pwd
/home/jneves/LM
$ cd bin
$ pwd
/usr/local/bin
Como /usr/local estaba en mi variable
$ date
Thu Apr 14 11:54:13 BRT 2005
$ LANG=pt_BR date
Qui Abr 14 11:55:14 BRT 2005
Con la especificación de la variable
$ who
jneves pts/0 Apr 11 16:26 (10.2.4.144)
jneves pts/1 Apr 12 12:04 (10.2.4.144)
$ who | grep ^botelho
$ echo ${PIPESTATUS[*]}
0 1
En este ejemplo mostramos que el usuário
Para generar randómicamente un entero entre 0 y 100, hacemos: $ echo $((RANDOM%101))
73
O sea, tomamos el resto de la división por
$ read -p "Digite S o N: "
Digite S o N: N
$ echo $REPLY
N
Yo soy de la época en que la memoria era un bien precioso que costaba muuuuy caro. Entonces para tomar un Expansión de parámetrosBien, mucho de lo que vimos hasta ahora son comandos externos al Shell. Estos son de gran ayuda, facilitan la visualización, manutención y depuración del código, pero no son tan eficientes como los intrínsecos (built-ins). Cuando nuestro problema sea prestaciones, debemos dar preferencia al uso de los intrínsecos y a partir de ahora te voy a mostrar algunas técnicas para que tu programa pise el acelerador.
En la tabla y ejemplos siguientes, veremos una serie de construcciones llamadas expansión (o substitución) de parámetros (Parameter Expansion), que substituyen instrucciones como el
SN=$(SN:-S}
De esta forma si el operador dió un simple
$ cadena=0123
$ echo ${#cadena}
4
$ cadena=abcdef
$ echo ${cadena:1}
bcdef
Fíjate que el origen es cero y no uno.
$ echo ${cadena:2:3}
cde
Fíjate que nuevamente el origen de la posición es cero y no uno.
$ cadena="Conversa de Bar"
$ echo ${cadena#*' '}
de Bar
$ echo "Conversa "${cadena#*' '}
Conversa de Bar
En este ejemplo fue suprimido a la izquierda todo lo que estuviera antes de la ocurrencia de la expresión Estos ejemplos también podrían ser escritos sin proteger el espacio de la interpretación del Shell (pero prefiero protegerlo para facilitar a legibilidad del código), mira: $ echo ${cadena#* }
de Bar
$ echo "Conversa "${cadena#* }
Conversa de Bar
Fíjate que en la construcción de
$ echo ${cadena##*' '}
Bar
$ echo "Vamos 'Chopear' en el "${cadena##*' '}
Vamos 'Chopear' en el Bar
Esta vez suprimimos a la izquierda de la cadena la mayor ocurrencia de la expresión
Otro ejemplo mas útil: para que no aparezca el camino (path) completo de tu programa (que, como ya sabemos está contenido en la variable echo Uso: ${0##*/} texto del mensaje de error
En este ejemplo sería suprimido por la izquerda todo hasta la última barra (
* El uso de porcentaje ( $ echo $cadena
Conversa de Bar
$ echo ${cadena%' '*}
Conversa de
$ echo ${cadena%%' '*}
Conversa
$ echo $cadena
Conversa de Bar
$ echo ${cadena/de/en el}
Conversa en el Bar
$ echo ${cadena/de /}
Conversa Bar
En este caso presta atención cuando vayas a usar metacaracteres, son unos comilones! Siempre combinarán con la mayor posibilidad, mira el ejemplo siguiente donde la intención era cambiar $ echo $cadena
Conversa de Bar
$ echo ${cadena/*a/Charla}
Charlar
La idea era cogerlo todo hasta la primera
$ echo ${cadena/*sa/Charla}
Charla de Bar
$ echo ${cadena/????????/Charla}
Charla de Bar
* Cambiando todas las ocurrencias de una subcadena por otra. Cuando hacemos: $ echo ${cadena//a/o}
Converso de Bor
Cambiamos todas las letras $ ls | wc -l
30
Viste? El $ CtdArChs=$(ls | wc -l) # CtdArchs recibe la salida del comando
$ echo ${CtdArChs// /}
30
En el último ejemplo, como sabía que la salida era compuesta de blancos y números, monté esta expresión para cambiar todos los espacios por nada. Fíjate que después de las dos primeras barras existe un espacio en blanco. Otra forma de hacer la misma cosa sería: $ echo ${CtdArChs/* /}
30
$Pájaro="quero quero"
$ echo $Pájaro
quero quero
$ echo "Como dice el gaucho - "${Pájaro/#quero/no}
Como dice el gaucho - no quero
Para cambiarla al final hacemos:
$ echo "Como se dice en el norte - "${Pájaro/%quero/no}
Como se dice en el norte - quero no
- Ahora basta, la conversación de hoy fue muy aburrida porque hay muchas cosas para memorizar, así que lo principal es que hayas entendido lo que te dije y cuando lo necesites, consultes estas servilletas en las que escribí estas ayudas y después guárdalas para futuras consultas. Pero volviendo a lo que importa, ha llegado la hora de tomar otro y ver el partido de futbol. Para la próxima te voy a aflojar un poco y solo te voy a pedir lo siguiente: toma la rutina
- Mozo, no se olvide de mi y llene mi vaso. 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 - 23 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. |