You are here:
Wiki-SL
>
TWikiBar Web
>
TWikiBarConversa009
(18 Feb 2008,
CollonsTorre
)
(raw view)
E
dit
A
ttach
---+!! Conversación de Bar Parte IX --- %TOC% --- - 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 =listartista= con la pantalla formateada, en _loop_, de forma que solamente termine cuando reciba un =<ENTER>= puro en el nombre del artista. Eventuales mensajes de error y preguntas deberían ser mostradas en la antepenúltima línea de la pantalla utilizando las rutina =mandamsj.func= y =pregunta.func= que acabamos de desarrollar. - Primero optimize el =mandamsj.func= y el =pregunta.func=, que quedaron así: %TERMINAL_INI% $ cat mandamsj.func%OUT_INI% # 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="$*" <nop>TamMsj=${#Msj} Col=$(((<nop>TotCols - <nop>TamMsj) / 2)) # Centra msj en la línea tput cup $líneaMesj $Col read -n1 -p "$Msj "%OUT_FIM% %TERMINAL_FIM% %TERMINAL_INI% $ cat pregunta.func%OUT_INI% # 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`)" <nop>TamMsj=${#Msj} Col=$(((<nop>TotCols - <nop>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%OUT_FIM% %TERMINAL_FIM% - Y aquí va el grandullón ahora: %TERMINAL_INI% $ cat listartista3%OUT_INI% #!/bin/bash # Dado un artista, muestra sus músicas # versión 3 <nop>líneaMesj=$((`tput lines` - 3)) # línea que msjs serán dados al operador <nop>TotCols=$(tput cols) # Ctd de columnas de la pantalla para encuadre de msjs clear echo " +----------------------------------------------------+ <nop>| Lista Todas las Músicas de un Determinado Artista | <nop>| ----- ----- -- ------- -- -- ----------- ------- | <nop>| | <nop>| 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 '| |' <nop>LinActual=8 IFS=" :" for <nop>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 <nop>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 '| |' <nop>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%OUT_FIM% %TERMINAL_FIM% - 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 =tput=. Vamos a comprobar el resultado con un álbum de _Emerson, Lake & Palmer_ que tengo registrado: <verbatim> +----------------------------------------------------+ | 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----------+ </verbatim> ---++ 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:%BR% - Pero, no era con el comando =echo= y con los redireccionamentos de salida que se escribe? 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= - su sintaxis es la siguiente: <verbatim> printf formato [argumento...] </verbatim> En donde:%BR% =formato= - es una cadena de caracteres que contiene 3 tipos de objetos: 1. caracteres simples; 1. caracteres para especificación de formato; 1. secuencia de escape en el patrón del lenguaje C.%BR% =Argumento= - es la cadena a ser impresa con el control del =formato=. Cada uno de los caracteres utilizados para especificación de =formato= está precedido por el carácter =%= y luego viene la especificación de =formato= de acuerdo con la tabla: <center> %TABLE{ sort="off" tableborder="0" cellpadding="4" cellspacing="1" headerbg="#0000FF" headercolor="#FFFF00" databg="#BBBBBB,#DDDDDD" headerrows="2" footerrows="1" }% | *Tabla de los Caracteres de Formatación del printf* || | *Letra* | *La expresión será impresa como:* | | =c= | Simple caracter | | =d= | Número en sistema decimal | | =e= | Notación científica exponencial | | =f= | Número con punto decimal (_float_) | | =g= |El menor entre los formatos =%e= y =%f= con supresión de los ceros no significativos | | =o= | Número en sistema octal | | =s= | Cadena de caracteres | | =x= | Número en sistema hexadecimal | | =%= | Imprime un =%=. no existe ninguna conversión | </center> Las secuencias de _escape_ patrón del lenguaje C son siempre precedidas por una barra invertida (=\=) y las reconocidas por el comando =printf= son: <center> %TABLE{ sort="off" tableborder="0" cellpadding="4" cellspacing="1" headerbg="#0000FF" headercolor="#FFFF00" databg="#BBBBBB,#DDDDDD" headerrows="2" footerrows="1" }% | *Secuencias de _Escape_ del printf* || | *Secuencia* | *Efecto* | | =a= | Suena el bip | | =b= | Vuelve una posición (_backspace_) | | =f= | Salta para la próxima página lógica (_form feed_) | | =n= | Salta para el inicio de la línea siguiente (_line feed_) | | =r= | Vuelve para el inicio de la línea actual (_carriage return_) | | =t= | Avanza para la próxima marca de tabulación | </center> 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. %TERMINAL_INI% $ printf "%c" "1 caracter"%OUT_INI% 1%OUT_FIM%$ %T2%Error! Sólo listó 1 caracter y no saltó de línea al final%T0% $ printf "%c\n" "1 caracter"%OUT_INI% 1%OUT_FIM% %T2%Saltó de línea pero todavia no listó la cadena entera%T0% $ printf "%c caracteres\n" 1%OUT_INI% 1 caracter%OUT_FIM% %T2%Esta es la forma correcta, el %c recebió el 1%T0% $ a=2 $ printf "%c caracteres\n" $a%OUT_INI% 2 caracteres%OUT_FIM% %T2%O %c recibió el valor de la variable $a%T0% $ printf "%10c caracteres\n" $a%OUT_INI% 2 caracteres%OUT_FIM% $ printf "%10c\n" $a caracteres%OUT_INI% 2 c%OUT_FIM% %TERMINAL_FIM% Observa que en los dos últimos ejemplos, en virtud del =%c=, sólo se listo un caracter de cada cadena. El =10= delante de la =c=, no significa 10 caracteres. Un número después del signo de porcentaje (=%=) significa el tamaño que la cadena tendrá depués de la ejecución del comando. Y aqui vá un ejemplo: %TERMINAL_INI% $ printf "%d\n" 32%OUT_INI% 32%OUT_FIM% $ printf "%10d\n" 32%OUT_INI% 32%OUT_FIM% %T2%Rellena con blancos a la izquierda y con ceros%T0% $ printf "%04d\n" 32%OUT_INI% 0032%OUT_FIM% %T2%04 despues % significa 4 dígitos con ceros a la izquierda%T0% $ printf "%e\n" $(echo "scale=2 ; 100/6" | bc)%OUT_INI% 1.666000e+01%OUT_FIM% %T2%El default del %e es 6 decimales%T0% $ printf "%.2e\n" `echo "scale=2 ; 100/6" | bc`%OUT_INI% 1.67e+01%OUT_FIM% %T2%El .2 especificó dos decimales%T0% $ printf "%f\n" 32.3%OUT_INI% 32.300000%OUT_FIM% %T2%El default del %f es 6 decimales%T0% $ printf "%.2f\n" 32.3%OUT_INI% 32.30%OUT_FIM% %T2%El .2 especificó dos decimales%T0% $ printf "%.3f\n" `echo "scale=2 ; 100/6" | bc`%OUT_INI% 33.330%OUT_FIM% %T2%El bc devolvió 2 decimales. El printf colocó 0 a la derecha%T0% $ printf "%o\n" 10%OUT_INI% 12%OUT_FIM% %T2%Convirtió el 10 en octal%T0% $ printf "%03o\n" 27%OUT_INI% 033%OUT_FIM% %T2%Así la conversión queda con más apariencia de octal, sí?%T0% $ printf "%s\n" Palabra%OUT_INI% Palabra%OUT_FIM% $ printf "%15s\n" Palabra%OUT_INI% Palabra%OUT_FIM% %T2%Palabra con 15 caracteres rellenados con blancos%T0% $ printf "%-15sNeves\n" Palabra%OUT_INI% Palabra Neves%OUT_FIM% %T2%El menos (-) rellenó a la derecha con blancos%T0% $ printf "%.3s\n" Palabra%OUT_INI% Pal%OUT_FIM% %T2%3 Corta y deja sólo las 3 primeras%T0% $ printf "%10.3sa\n" Peteleca%OUT_INI% Peta%OUT_FIM% %T2%Pet con 10 caracteres concatenado con a (después del s)%T0% $ printf "EJEMPLO %x\n" 45232%OUT_INI% EJEMPLO b0b0%OUT_FIM% %T2%Transformó en hexa pero los zeros no combinan%T0% $ printf "EJEMPLO %X\n" 45232%OUT_INI% EJEMPLO B0B0%OUT_FIM% %T2%Así quedó mejor (Fíjate en la X mayúscula) %T0% $ printf "%X %XL%X\n" 49354 192 10%OUT_INI% C0CA C0LA%OUT_FIM% %TERMINAL_FIM% El último ejemplo no es _marketing_ y es bastante completo, voy a comentarlo paso a paso: 1. El primer =%X= convirtió =49354= en hexadecimal resultando =C0CA= (léase "ce", "cero", "ce" y "a"); 1. En seguida viene un espacio en blanco seguido por otro =%XL=. El =%X= convirtió el =192= dando como resultado =C0= que con el =L= hizo =C0L=; 1. Y finalmente el último =%X= transformó el =10= en =A=. Como puedes notar, la instrucción =printf= es bastante completa y compleja (por suerte el =echo= lo resuelve casi todo). Creo que cuando me decidí a explicar el =printf= a través de ejemplos, acerté plenamente, porque no sabria como enumerar tantas reglitas sin hacer la lectura aburrida. ---++ Principales Variables del _Shell_ El _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: <center> %TABLE{ sort="off" tableborder="0" cellpadding="4" cellspacing="1" headerbg="#0000FF" headercolor="#FFFF00" databg="#BBBBBB,#DDDDDD" headerrows="2" footerrows="1" }% | *Principales variables del Bash* || | *Variável* |<nop> *Conteúdo* | | CDPATH | Contiene los caminos que serán recorridos para intentar localizar un directório especificado. A pesar de ser esta variable poco conocida, su uso debe ser incentivado por que nos ahorra mucho trabajo, principalmente en instalaciones con estructuras de directórios con bastante niveles. | | HISTSIZE | Limita el número de instrucciones que caben dentro del archivo histórico de comandos (normalmente =.bash_history= pero efectivamente es lo que está almacenado en la variable =$HISTFILE=). Su valor _default_ es 500. | | HOSTNAME | El nombre del host actual (que también puede ser obtenido con el comando =uname -n=). | | LANG | Usada para determinar el idioma hablado en el país (más especificamente categoria de locale). | | LINENO | El número de la línea del _script_ o de la función que está siendo ejecutada, su uso principal es para dar mensajes de error juntamente con las variables =$0= (nombre del programa) y =$FUNCNAME= (nombre de la función en ejecución) | | LOGNAME | Almacena el nombre de _login_ del usuário. | | MAILCHECK | Especifica, en segundos, la frecuencia con que el Shell verificará la presencia de correspondencia en los archivos indicados por las variables =$MAILPATH= o =$MAIL=. El tiempo patrón es de 60 segundos. Una vez que este tiempo expira, el _Shell_ hará esta verificación antes de exhibir el próximo _prompt_ primario (definido en =$PS1=). Si esta variable estuviera sin valor o con un valor menor o igual a cero, la verificación de nueva correspondencia no será efectuada. | | PATH | Caminos que serán recorridos para intentar localizar un archivo especificado. Como cada _script_ es un archivo, en el caso de que uses el directorio actual (=.=) en su variable =$PATH=, no necesitarás usar el =./scrp= para que =scrp= sea ejecutado. Basta hacer =scrp=. Este es el modo en que procedo aqui en el Bar. | | PIPESTATUS | Es una variable del tipo vector (_array_) que contiene una lista de valores de código de retorno del último _pipeline_ ejecutado, o sea, un _array_ que abriga cada uno de los =$?= de cada instrucción del último _pipeline_. | | PROMPT_COMMAND | Si esta variable recibe una instrucción, cada vez que tu des un =<ENTER>= directo en el prompt principal (=$PS1=), este comando será ejecutado. Es útil cuando se está repitiendo mucho una determinada instrucción. | | PS1 | Es el _prompt_ principal. En "Conversa de Bar" usamos sus _defaults_: =$= para el usuário común y =#= para el _root_, pero es muy frecuente que esté personalizado. Una curiosidad es que existen hasta concursos de quien programa el =$PS1= más creativo. <a href="http://www.google.com.br/search?num=100&hl=pt-BR&q=+%22PS1%22++Linux++prompt+personalizar+alterar&btnG=Pesquisar&meta=cr=countryBR" target="_blank">(clique para dar una googlada)</a> | | PS2 | También llamado _prompt_ de continuación, es aquél signo de mayor (=>=) que aparece después de un =<ENTER>= sin que el comando haya sido finalizado. | | PWD | Posee el camino completo (=$PATH=) del directório actual. Tiene el mismo efecto que el comando =pwd=. | | RANDOM | Cada vez que esta variable es llamada, devuelve un número entero, que es un número randómico entre 0 y 32767. | | REPLY | Usa esta variable para recuperar el último campo leído, en caso de que no tenga ninguna variable asociada. | | SECONDS | Esta variable contiene la cantidad de segundos en que el _Shell_ actual está en uso. Úsala solamente para mostrar a un usuario aquello que llaman de sistema operacional, pero necesita de frecuentes _boots_. :) | | TMOUT | Si tuviera un valor mayor que cero, este valor será tomado como el patrón de _timeout_ del comando =read=. En el _prompt_, este valor es interpretado como el tiempo de espera a una acción antes de finalizar la sesión. Suponiendo que la variable contenga 30, el _Shell_ dará _logout_ 30 segundos después que el _prompt_ esté sin ninguna acción. | </center> * *CDPATH* %TERMINAL_INI% $ echo $CDPATH%OUT_INI% .:..:~:/usr/local%OUT_FIM% $ pwd%OUT_INI% /home/jneves/LM%OUT_FIM% $ cd bin $ pwd%OUT_INI% /usr/local/bin%OUT_FIM% %TERMINAL_FIM% Como /usr/local estaba en mi variable =$CDPATH=, y no existía el directório =bin= en ninguno de sus antecesores (=.=, =..= e =~=), el =cd= fue ejecutado para =/usr/local/bin= * *LANG* %TERMINAL_INI% $ date%OUT_INI% Thu Apr 14 11:54:13 BRT 2005%OUT_FIM% $ LANG=pt_BR date%OUT_INI% Qui Abr 14 11:55:14 BRT 2005%OUT_FIM% %TERMINAL_FIM% Con la especificación de la variable =LANG=pt_BR= (portugués de Brasil), la fecha pasó a ser formateada en el patrón brasileño. Es interesante observar que no se uso punto y coma (=;=) para separar la atribución de =LANG= del comando =date=. * *PIPESTATUS* %TERMINAL_INI% $ who%OUT_INI% jneves pts/0 Apr 11 16:26 (10.2.4.144) jneves pts/1 Apr 12 12:04 (10.2.4.144)%OUT_FIM% $ who | grep ^botelho $ echo ${PIPESTATUS[*]}%OUT_INI% 0 1%OUT_FIM% %TERMINAL_FIM% En este ejemplo mostramos que el usuário =botelho= no estaba "logado", en seguida ejecutamos un _pipeline_ que lo filtraba. Se usa la notación =[*]= en un _array_ para listar todos sus elementos, y de esta forma vimos que la primera instrucción (=who=) fue bien ejecutada (código de retorno 0) y la siguiente (=grep=), no (código de retorno 1). * *RANDOM* Para generar randómicamente un entero entre 0 y 100, hacemos: %TERMINAL_INI% $ echo $((RANDOM%101))%OUT_INI% 73%OUT_FIM% %TERMINAL_FIM% O sea, tomamos el resto de la división por =101= del número randómico generado, porque el resto de la división de cualquier número por 101 varía entre 0 y 100. * *REPLY* %TERMINAL_INI% $ read -p "Digite S o N: "%OUT_INI% Digite S o N:%OUT_FIM% N $ echo $REPLY%OUT_INI% N%OUT_FIM% %TERMINAL_FIM% Yo soy de la época en que la memoria era un bien precioso que costaba muuuuy caro. Entonces para tomar un =S= o un =N=, no acostumbro guardar un espacio especial y por lo tanto, tomo de la variable =$REPLY= lo que se escribio. ---++ Expansión de parámetros Bien, 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 =cut=, el =expr=, el =tr=, el =sed= y otras, de forma más ágil. <center> %TABLE{ sort="off" tableborder="0" cellpadding="4" cellspacing="1" headerbg="#0000FF" headercolor="#FFFF00" databg="#BBBBBB,#DDDDDD" headerrows="2" footerrows="1" }% | *Expansión de parámetros* || | *Expresión* | *Resultado esperado* | | =${var:-padrón}= | Si =var= no tiene valor, el resultado de la expresión es =padrón= | | =${#cadena}= | Tamaño de =$cadena= | | =${cadena:posición}= | Extrae una sub-cadena de =$cadena= a partir de =posición=. Origen cero | | =${cadena:posición:tamaño}= | Extrae una sub-cadena de =$cadena= a partir de =posición= con tamaño igual a =tamaño=. Origen cero | | =${cadena#expr}= | Corta la menor ocurrencia de =$cadena= a la izquierda de la expresión =expr= | | =${cadena##expr}= | Corta la mayor ocurrencia de =$cadena= a la izquierda de la expresión =expr= | | =${cadena%expr}= | Corta la menor ocurrencia de =$cadena= a la derecha de la expresión =expr= | | =${cadena%%expr}= | Corta la mayor ocurrencia de =$cadena= a la derecha de la expresión =expr= | | =${cadena/subcad1/subcad2}= | Cambia en =$cadena= la primera ocurrencia de =subcad1= por =subcad2= | | =${cadena//subcad1/subcad2}= | Cambia en =$cadena= todas las ocurrencias de =subcad1= por =subcad2= | | =${cadena/#subcad1/subcad2}= | Si =subcad1= es igual al inicio de =$cadena=, entonces es cambiada por =subcad2= | | =${cadena/%subcad1/subcad2}= | Si =subcad1= s igual al fin de =$cadena=, entonces es cambiada por =subcad2= | </center> * Si en una pregunta el =S= es ofrecido como valor _default_ (patrón) y la salida va hacia la variable =$SN=, después de leer el valor podemos hacer: <verbatim> SN=$(SN:-S} </verbatim> De esta forma si el operador dió un simple =<ENTER>= para confirmar que aceptó el valor _default_, después de ejecutar esta instrucción, la variable tendrá el valor =S=, en caso contrário, tendrá el valor tecleado. * Para saber el tamaño de una cadena: %TERMINAL_INI% $ cadena=0123 $ echo ${#cadena}%OUT_INI% 4%OUT_FIM% %TERMINAL_FIM% * Para extraer de una cadena de la posición uno hasta el final hacemos: %TERMINAL_INI% $ cadena=abcdef $ echo ${cadena:1}%OUT_INI% bcdef%OUT_FIM% %TERMINAL_FIM% Fíjate que el origen es cero y no uno. * En la misma variable =$cadena= del ejemplo de arriba, para extraer 3 caracteres a partir de la 2ª posición: %TERMINAL_INI% $ echo ${cadena:2:3}%OUT_INI% cde%OUT_FIM% %TERMINAL_FIM% Fíjate que nuevamente el origen de la posición es cero y no uno. * Para suprimir todo a la izquierda de la primera ocurrencia de una cadena, haz: %TERMINAL_INI% $ cadena="Conversa de Bar" $ echo ${cadena#*' '}%OUT_INI% de Bar%OUT_FIM% $ echo "Conversa "${cadena#*' '}%OUT_INI% Conversa de Bar%OUT_FIM% %TERMINAL_FIM% En este ejemplo fue suprimido a la izquierda todo lo que estuviera antes de la ocurrencia de la expresión =*' '=, o sea, todo hasta el primer espacio en blanco. 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: %TERMINAL_INI% $ echo ${cadena#* }%OUT_INI% de Bar%OUT_FIM% $ echo "Conversa "${cadena#* }%OUT_INI% Conversa de Bar%OUT_FIM% %TERMINAL_FIM% Fíjate que en la construcción de =expr= está permitido el uso de metacaracteres. * Utilizando el mismo valor de la variable =$cadena=, observa como haríamos para tener solamente =Bar=: %TERMINAL_INI% $ echo ${cadena##*' '}%OUT_INI% Bar%OUT_FIM% $ echo "Vamos 'Chopear' en el "${cadena##*' '}%OUT_INI% Vamos 'Chopear' en el Bar%OUT_FIM% %TERMINAL_FIM% Esta vez suprimimos a la izquierda de la cadena la mayor ocurrencia de la expresión =expr=. Así como en el caso anterior, el uso de metacaracteres está permitido. Otro ejemplo mas útil: para que no aparezca el camino (_path_) completo de tu programa (que, como ya sabemos está contenido en la variable =$0=) en un mensaje de error, empieza tu texto de la siguiente forma: <verbatim> echo Uso: ${0##*/} texto del mensaje de error </verbatim> En este ejemplo sería suprimido por la izquerda todo hasta la última barra (=/=) del camino (_path_), quedando solamente el nombre del programa. * El uso de porcentaje (=%=) es como si mirasemos el simbolo (=#=) en el espejo, o sea, son simétricos. Veamos un ejemplo para probarlo: %TERMINAL_INI% $ echo $cadena%OUT_INI% Conversa de Bar%OUT_FIM% $ echo ${cadena%' '*}%OUT_INI% Conversa de%OUT_FIM% $ echo ${cadena%%' '*}%OUT_INI% Conversa%OUT_FIM% %TERMINAL_FIM% * Para cambiar la primera ocurrencia de una sub-cadena en una cadena por otra: %TERMINAL_INI% $ echo $cadena%OUT_INI% Conversa de Bar%OUT_FIM% $ echo ${cadena/de/en el}%OUT_INI% Conversa en el Bar%OUT_FIM% $ echo ${cadena/de /}%OUT_INI% Conversa Bar%OUT_FIM% %TERMINAL_FIM% 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 =Conversa de Bar= por =Charla de Bar=: %TERMINAL_INI% $ echo $cadena%OUT_INI% Conversa de Bar%OUT_FIM% $ echo ${cadena/*a/Charla}%OUT_INI% Charlar%OUT_FIM% %TERMINAL_FIM% La idea era cogerlo todo hasta la primera =a=, pero lo que cambio fue todo hasta la última =a=. Esto podría resolverse de diversas formas, veamos algunas: %TERMINAL_INI% $ echo ${cadena/*sa/Charla}%OUT_INI% Charla de Bar%OUT_FIM% $ echo ${cadena/????????/Charla}%OUT_INI% Charla de Bar%OUT_FIM% %TERMINAL_FIM% * Cambiando todas las ocurrencias de una subcadena por otra. Cuando hacemos: %TERMINAL_INI% $ echo ${cadena//a/o}%OUT_INI% Converso de Bor%OUT_FIM% %TERMINAL_FIM% Cambiamos todas las letras =a= por =o=. Otro ejemplo más útil es para contar la cantidad de archivos existentes en el directorio en uso. Observa la linea siguiente: %TERMINAL_INI% $ ls | wc -l%OUT_INI% 30%OUT_FIM% %TERMINAL_FIM% Viste? El =wc= produce una cantidad de espacios en blanco al inicio. Para eliminarlos podemos hacer: %TERMINAL_INI% $ <nop>CtdArChs=$(ls | wc -l) # <nop>CtdArchs recibe la salida del comando $ echo ${CtdArChs// /}%OUT_INI% 30%OUT_FIM% %TERMINAL_FIM% 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: %TERMINAL_INI% $ echo ${CtdArChs/* /}%OUT_INI% 30%OUT_FIM% %TERMINAL_FIM% * Cambiando una sub-cadena en el inicio o en el fin de una variable. Vamos a usar como ejemplo el conocido pájaro del campo "Quero quero", conocido en otros países como "Tero tero". Para cambiarla al inicio hacemos: %TERMINAL_INI% $Pájaro="quero quero" $ echo $Pájaro%OUT_INI% quero quero%OUT_FIM% $ echo "Como dice el gaucho - "${Pájaro/#quero/no}%OUT_INI% Como dice el gaucho - no quero%OUT_FIM% %TERMINAL_FIM% Para cambiarla al final hacemos: %TERMINAL_INI% $ echo "Como se dice en el norte - "${Pájaro/%quero/no}%OUT_INI% Como se dice en el norte - quero no%OUT_FIM% %TERMINAL_FIM% - 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 =pregunta.func=, (de la cual hablamos en el inicio de nuestra conversa de hoy) y optimízala para que la variable =$SN= reciba el valor _default_ por expansión de parámetros, como vimos. - 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 <a href="mailto:julio.neves@gmail.com?Subject=Dudas Conversas de bar botequim">julio.neves@gmail.com</a>. 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 <a href="mailto:julio.neves@uniriotec.br?Subject=Curso de Shell con Julio Neves">julio.neves@uniriotec.br</a> para informarse. Gracias y hasta la <a href="https://twiki.softwarelivre.org/bin/view/TWikiBar/TWikiBarConversa10">próxima</a> -- Main.HumbertoPina - 23 Jan 2007
E
dit
|
A
ttach
|
P
rint version
|
H
istory
: r9
<
r8
<
r7
<
r6
<
r5
|
B
acklinks
|
V
iew topic
|
M
ore topic actions
Topic revision: r9 - 18 Feb 2008 - 23:10:32 -
CollonsTorre
TWikiBar
Página Inicial
Últimas alterações
Índice
Procurar
Estatísticas de Uso
Aviso de Atualização
Configurações Gerais
Projeto Gráfico
Mapa do Site
Quem Somos
Registre-se
?
Regras de Formatação
Biblioteca Gráfica
?
Carinhas Gráficas
Webs Wiki-SL
Amadeu
Anapolivre
ArquivoLivre
Arte
BahiaSocial
BeaBa
BibliotecaLivre
Blogs
BrasilDigital
BrasilELivre
BSM
Ccsa
CESL
CoberturaWiki
Cooperativas
Curriculo
DarvinMarosin
DiaD
Dinamicoop
Economia
EconomiaSolidaria
EducacaoLivre
Ekaaty
Emacsbr
ENSL
Fatos
Festival3
Festival4
Flisol
Fmpb
Formatos
Foswikibr
FSM2005
GNOMEBR
GTTemario2004
GTWeb
Guialivre
HDC
Incubus
InkscapeBrasil
Jogos
KdeBR
KSP
LGM
LinuxStokDoc
Livros
Main
Mentores
MHHOB
MinuanoDigital
MoradiaECidadania
OlhosDagua
Olimpo
OLPC
OOPTQ
Papers
PCLivre
PentahoBrasil
Pessoas
Portal
Prefeituras
PSLAL
PSLBA
PSLBancarios
PSLBrasil
PSLGO
PSLMA
PSLMG
PSLMIP
PSLMT
PSLMulheres
PSLPI
PubFisl10
PubFisl7
PubFisl8
PubFisl9
QuilomboDoSopapo
RadioSL
RedeMesh
RedePopular
RobotWars
Sandbox
Saudelivre
Scribus
Sementes
Shakya
SLRJ
SoftwareLivreIrece
SoftwareLivreVS
SoLiSC
SuporteLivre
System
Telecentros
TeseSA
TextoLivre
TV
TWikiBar
TWikiPtbr
UNELivre
UNIMIX
VilaTorres
WebNordeste
WTRD2004
Este Menu
?skin=free
English
Español
Português brasileiro
Copyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Wiki-SL?
Send feedback