Difference: TWikiBarConversa002 (1 vs. 11)

Revision 1114 Feb 2012 - MarioSilva

Line: 1 to 1
 

Conversación de Bar Parte II

Line: 443 to 443
 

-- HumbertoPina - 13 Sep 2006

Added:
>
>

Revision 1003 Feb 2008 - JulioNeves

Line: 1 to 1
Changed:
<
<

Conversa de Bar Parte II

>
>

Conversación de Bar Parte II

 

Revision 929 Jan 2008 - CollonsTorre

Line: 1 to 1
 

Conversa de Bar Parte II

Changed:
<
<
    - Mozo! Trae un "chopps" e dos "pastel". Mi amigo hoy no va a beber porque él finalmente está siendo presentado a un verdadero sistema operativo y todavia tiene mucha cosa para aprender!
    - Y entonces, amigo, está entendiendo todo lo que te expliqué hasta ahora?
>
>
    - Mozo! Trae un "chopps" y dos "pastel". Mi amigo hoy no va a beber porque finalmente le está siendo presentado un verdadero sistema operativo y todavia tiene muchas cosas que aprender!
    - Y entonces, amigo, estas entendiendo todo lo que te expliqué hasta ahora?
     - Entendiendo estoy, pero no vi nada práctico en eso...
Changed:
<
<
    - Calma, lo que te dije hasta ahora, sirve como base para lo que ha de venir de aqui en adelante. Vamos a usar estas herramientas que vimos para montar programas estructurados, que el Shell te permite. Entonces tu verás por qué hasta en la TV ya hubo un programa llamado "El Shell es el Límite".
>
>
    - Calma, lo que te dije hasta ahora, sirve como base para lo que ha de venir de aquí en adelante. Vamos a usar estas herramientas que vimos para montar programas estructurados, que el Shell te permite. Entonces verás por qué hasta en la TV hubo un programa llamado "El Shell es el Límite".
     - Para comenzar vamos a hablar de los comandos de la familia grep.
    - grep? No conozco ningún término en inglés con este nombre...
Changed:
<
<
    - Por supuesto, grep es un acrónimo Global Regular Expression Print, que usa expresiones regulares para buscar la ocurrencia de cadenas de caracteres en la entrada definida (si bien que hay una leyenda sobre como este comando fue bautizado: en el editor de textos "ed", el abuelo del "vim", el comando usado para buscar era g/_expresión regular_/p, en inglés g/_re_/p). Por hablar en expresiones regulares (o regexp), el portal BULMA - Bisoños Usuarios de GNU/Linux de Mallorca y Alrededores tiene todas las dicas en su página (inclusive tutoriales) que abordan el tema. Si estás realmente con ganas de aprender a programar en Shell, Perl, Python, ... debes leer estos artículos que te ayudarán a resolver lo que nos espera más adelante.
>
>
    - Por supuesto, grep es un acrónimo Global Regular Expression Print, que usa expresiones regulares para buscar la ocurrencia de cadenas de caracteres en la entrada definida (has de saber que hay una leyenda sobre como fue bautizado este comando: en el editor de textos "ed", el abuelo del "vim", el comando usado para buscar era g/_expresión regular_/p, en inglés g/_re_/p). Por hablar en expresiones regulares (o regexp), el portal BULMA - Bisoños Usuarios de GNU/Linux de Mallorca y Alrededores tiene todos los enlaces en su página (inclusive tutoriales) que abordan el tema. Si realmente tienes ganas de aprender a programar en Shell, Perl, Python, ... debes leer estos artículos que te ayudarán a resolver lo que nos espera más adelante.
 

Me quedo con el grep, tú con la gripe

Changed:
<
<
Eso de la gripe es un sólo un decir! Simplemente un pretexto para pedir unas "Caipirinhas" (o caipiriñas, el coctel oficial del carnaval brasileño wink - vea cómo prepararlas). Volviendo a nuestro tema, te dije que que el grep busca cadenas de caracteres dentro de una entrada definida, pero en realidad... que viene a ser una "entrada definida"? Bueno, existen varias formas de definir la entrada del comando grep. Veamos:
>
>
Eso de la gripe es un sólo un decir! Simplemente un pretexto para pedir unas "Caipirinhas" (o caipiriñas, el coctel oficial del carnaval brasileño wink - vea cómo prepararlas). Volviendo a nuestro tema, te dije que el grep busca cadenas de caracteres dentro de una entrada definida, pero en realidad... que viene a ser una "entrada definida"? Bueno, existen varias formas de definir la entrada del comando grep. Veamos:
 Buscando en un archivo:

Line: 32 to 32
 $ who | grep Pelegrino
Changed:
<
<
En el 1º ejemplo, el más simple, busqué la palabra rafael en qualquier lugar del archivo /etc/passwd. Si quisiera buscarla como un login name, o sea, solamente en el inicio de los registros de este archivo, deberia hacer:
>
>
En el 1º ejemplo, el más simple, busqué la palabra rafael en cualquier lugar del archivo /etc/passwd. Si quisiera buscarla como un login name, o sea, solamente en el principio de los registros de este archivo, debería hacer:
 
$ grep '^rafael' /etc/passwd
Changed:
<
<
Y para que sirve este acento circunflejo y los apóstrofes? me vas a preguntar. El circunflejo (^), si hubieras leído los artículos anteriores sobre expresiones regulares que te dije, sabrías que sirven para limitar la búsqueda al inicio de cada línea, y los apóstrofes (') sirven para que el Shell no interprete este circunflejo, dejándolo pasar intacto para el comando grep.
>
>
Y para que sirve este acento circunflejo y los apostrofes? me vas a preguntar. Si hubieras leído los artículos anteriores sobre expresiones regulares que te dije, sabrías que el circunflejo (^) sirve para limitar la búsqueda al inicio de cada línea, y los apostrofes (') sirven para que el Shell no interprete este circunflejo, dejándolo pasar intacto para el comando grep.
  Mira que bien! El grep acepta como entrada, la salida de otro comando redireccionado por un pipe (esto es muy común en Shell y es un tremendo acelerador de la ejecución de comandos, ya que actúa como si la salida de un programa fuera guardada en disco y el segundo programa leyera este archivo generado), de esta forma, en el 3º ejemplo, el comando who listó las personas "logadas" en la misma máquina que tú (no te olvides jamás: el Linux es multiusuario) y el grep fue usado para verificar si Pelegrino estaba trabajando o simplemente "haciendo sebo".
Line: 56 to 56
 
  • El fgrep ("f" de fast, rápido, o de "file", archivo) como el nombre dice, es el rapidito de la familia, ejecuta el servicio de forma muy veloz (a veces es cerca de 30% más rápido que el grep y 50% más que el egrep), sin embargo no permite el uso de expresiones regulares en la búsqueda.

Pinguim com placa de atenção (em espanhol)
Changed:
<
<
Todo lo que fue dicho arriba sobre la velocidad, solamente se aplica a la familia de comandos grep del Unix. En Linux el grep es siempre más veloz, ya que los otros dos (fgrep y egrep) son scripts en Shell que llamam al primero y, ya estoy adelantando, no me gusta nada esta solución.
>
>
Todo lo que dije arriba sobre la velocidad, solamente se aplica a la familia de comandos grep del Unix. En Linux el grep es siempre más veloz, ya que los otros dos (fgrep y egrep) son scripts en Shell que llaman al primero y, ya me estoy adelantando, no me gusta nada esta solución.
      - Ahora que ya conoces las diferencias entre los miembros de la familia, dime: que te parecen los tres ejemplos que te dí antes de las explicaciones?
    - Me pareció que el fgrep resolvería tu problema de forma más veloz que el grep.
Line: 64 to 64
  Ejemplos
Changed:
<
<
Yo sé que en un archivo existe un texto hablando sobre Linux solo no sé si está escrito con L mayúsculo o l minúsculo. Puedo hacer la búsqueda de dos formas:
>
>
Yo sé que en un archivo existe un texto hablando sobre Linux solo que no sé si está escrito con L mayúscula o l minúscula. Puedo hacer la búsqueda de dos formas:
 
$ egrep (Linux | linux) archivo.txt
Changed:
<
<
ou
>
>
o
 
$ grep [Ll]inux archivo.txt
Changed:
<
<
En el primer caso, la expresión regular compleja "(Linux | linux)" usa los paréntesis para agrupar las opciones y la barra vertical (|) como un "o" lógico, o sea, estoy buscando Linux el linux.
>
>
En el primer caso, la expresión regular compleja "(Linux | linux)" usa los paréntesis para agrupar las opciones y la barra vertical (|) como un "o" lógico, o sea, estoy buscando Linux o linux.
 
Changed:
<
<
En el segundo, la expresión regular [Ll]inux significa: comenzando por L o l seguido de inux. Como esta expresión es más simple, el grep consigue resolverla, por lo tanto creo mejor usar la segunda forma, ya que el egrep dejaría la búsqueda más lenta.
>
>
En el segundo, la expresión regular [Ll]inux significa: comenzando por L o l seguido de inux. Como esta expresión es más simple, el grep consigue resolverla, por lo tanto creo que es mejor usar la segunda forma, ya que el egrep haría la búsqueda más lenta.
 
Changed:
<
<
Otro ejemplo. Para listar todos los subdirectórios del directório corriente, basta hacer:
>
>
Otro ejemplo. Para listar todos los subdirectorios del directorio actual, basta hacer:
 
$ ls -l | grep '^d'
Line: 97 to 97
 drwxr-xr-x 3 root root 4096 Dec 18 2000 xine
Changed:
<
<
En el ejemplo que acabamos de ver, el circunflejo (^) sirvió para limitar la pesquisa a la primera posición de la salida del ls detallado. los apóstrofes fueron colocados para que el Shell no "viera" el circunflejo (^).
>
>
En el ejemplo que acabamos de ver, el circunflejo (^) sirvió para limitar la busqueda a la primera posición de la salida del ls detallado. los apostrofes fueron colocados para que el Shell no "viera" el circunflejo (^).
 
Changed:
<
<
Vamos a ver otro. Sabemos que las cuatro primeras posiciones posibles de un ls -l de un archivo común (archivo común! No directório, ni link, ni ...) deben ser:
>
>
Vamos a ver otro. Sabemos que las cuatro primeras posiciones posibles de un ls -l de un archivo común (archivo común!, No directorio, ni link, ni ...) deben ser:
 
Line: 109 to 109
 
      -
Changed:
<
<
Así, para descubrir todos los archivos ejecutables en un determinado directório deberia hacer:
>
>
Así, para descubrir todos los archivos ejecutables en un determinado directorio debería hacer:
 
$ ls -la | egrep '^-..(x|s)'
Line: 118 to 118
 -rwxr-xr-x 1 root root 18453 Jul 6 17:28 rc.sysinit
Changed:
<
<
Donde nuevamente usamos el circunflejo (^) para limitar la búsqueda al inicio de cada línea, entonces las líneas listadas serán las que comiezan por un trazo (-), seguido de cualquier cosa (el punto cuando usado como una expresión regular significa cualquier cosa), nuevamente seguido de cualquer cosa, y siguiendo un x o un s.
>
>
Donde nuevamente usamos el circunflejo (^) para limitar la búsqueda al inicio de cada línea, entonces las líneas listadas serán las que comienzan por un trazo (-), seguido de cualquier cosa (el punto cuando es usado como una expresión regular significa cualquier cosa), nuevamente seguido de cualquier cosa, y siguiendo un x o un s.
 
Changed:
<
<
Obtendríamos el mismo resultado si hicieramos:
>
>
Obtendríamos el mismo resultado si hiciéramos:
 
$ ls -la | grep '^-..[xs]'
Line: 130 to 130
 

Vamos a montar una "CDteca"

Changed:
<
<
Vamos a comenzar a desarrollar programas, me parece que montar un banco de datos de músicas es muy útil y didático (y además práctico, en estos tiempos de downloads de mp3 y "quemadores" de CDs). No te olvides que, de la misma forma que vamos desarrollar una cantidad de programas para organizar tus CDs de música, con pequeñas adaptaciones, puedes hacer lo mismo con los CDs de software que vienen con la Linux Magazine y otros que compres o quemes, si disponibilizas este banco de software para todos los que trabajan contigo (el Linux es multiusuario, y como tal debe ser explotado), ganarás muchos puntos con tu adorado jefe.
>
>
Vamos a comenzar a desarrollar programas, me parece que montar un banco de datos de músicas es muy útil y didáctico (y además práctico, en estos tiempos de downloads de mp3 y "quemadores" de CDs). No te olvides que, de la misma forma vamos a desarrollar una cantidad de programas para organizar tus CDs de música, con pequeñas adaptaciones, puedes hacer lo mismo con los CDs de software que vienen con la Linux Magazine y otros que compres o quemes, si compartes este banco de software para todos los que trabajan contigo (el Linux es multiusuario, y como tal debe ser explotado), ganarás muchos puntos con tu adorado jefe.
      - Un momento! De donde voy la recibir los datos de los CDs?
    - Inicialmente, te voy a mostrar como tu programa puede recibir parámetros de quién lo esté ejecutando y en breve, te enseñaré a leer los datos por la pantalla o de un archivo.

Pasando parámetros

Changed:
<
<
El visual del archivo musicas será el siguiente:
>
>
El visual del archivo músicas será el siguiente:
       nombre del álbum^intérprete1~nombre de la música1:..:intérprete~nombre de la música
Changed:
<
<
o sea, el nombre del álbum será separado por un circunflejo (^) del resto del registro, que está formado por diversos grupos compuestos por el intérprete de cada música del CD y la respectiva música interpretada. Estos grupos son separados entre sí por dos-puntos (:) e internamente, el intérprete será separado por un til (~) del nombre de la música.
>
>
o sea, el nombre del álbum será separado por un circunflejo (^) del resto del registro, que está formado por diversos grupos compuestos por el intérprete de cada música del CD y la respectiva música interpretada. Estos grupos son separados entre sí por dos-puntos (:) e internamente, el intérprete será separado por una tilde (~) del nombre de la música.
  Escribiré un programa llamado musinc, que incluirá registros en mi archivo músicas. Pasaré el contenido de cada álbum como parâmetro en la llamada del programa de la siguiente forma:
Line: 169 to 169
 bash: test: cannot execute
Changed:
<
<
Opa! Me olvidé de hacerlo ejecutable. Voy a hacerlo de forma que permita que todos puedan ejecutarlo y en seguida voy a testarlo:
>
>
Opa! Me olvidé de hacerlo ejecutable. Voy a hacerlo de forma que permita que todos puedan ejecutarlo y en seguida voy a testearlo:
 
$ chmod 755 test
Line: 179 to 179
 3o. param -> para
Changed:
<
<
Repare que la palabra verificar, que sería el cuarto parámetro, no fue listada. Esto sucedió justamente porque el programa test solo listaba los tres primeros parámetros. Vamos ejecutarlo de otra forma:
>
>
Repara que la palabra verificar, que sería el cuarto parámetro, no fue listada. Esto sucedió justamente porque el programa test solo listaba los tres primeros parámetros. Vamos ejecutarlo de otra forma:
 
$ test "pasando parámetros" para verificar
Line: 192 to 192
 

Observaciones sobre parámetros

Changed:
<
<
Ya que estamos hablando en pasaje de parámetros observa bien lo siguiente:
>
>
Ya que estamos hablando de pasar parámetros observa bien lo siguiente:
 
Line: 210 to 210
 
$ cat test #!/bin/bash
Changed:
<
<
# Programa para verifivar el pasaje de parámetros (2a. Versao)
>
>
# Programa para verifivar el paso de parámetros (2a. Versao)
 echo El programa $0 recibió $# parámetros echo "1o. param -> $1" echo "2o. param -> $2"
Line: 249 to 249
 
$ test pasando parámetros para verificar
Changed:
<
<
El programa test recebió 4 parámetros que son:
>
>
El programa test recibió 4 parámetros que son:
 11o. param -> pasando1 2o. param -> parámetros 4o. param -> verificar
Line: 259 to 259
 
  1. Para mostrar que los nombres de los parámetros varían de $1 a $9 hice un echo $11 y que pasó? El Shell interpretó como que era $1 seguido del algarismo 1 y listó pasando1;
  2. El comando shift cuya sintáxis es shift n, pudiendo el n asumir cualquier valor numérico (sin embargo su default es 1, como en el ejemplo dado), desprecia los n primeros parámetros, devolviendo el parámetro de orden n+1, el primero o sea, el $1.
Changed:
<
<
Bueno, ahora que ya sabes más sobre pasaje de parámetros que yo mismo, vamos a voltar a nuestra "CDteca" para hacer el script para incluir los CDs en mi banco llamado musicas. El programa es muy simple (como todo en Shell) y voy a listarlo para que lo veas:
>
>
Bueno, ahora que ya sabes más sobre pasar parámetros que yo mismo, vamos a volver a nuestra "CDteca" para hacer el script que incluira los CDs en mi banco llamado musicas. El programa es muy simple (como todo en Shell) y voy a listarlo para que lo veas:
  Ejemplos
Line: 271 to 271
 echo $1 >> musicas
Changed:
<
<
El script es fácil y funcional, limítome a anexar al fin del archivo musicas el parámetro recibido. Vamos a incluir 3 álbunes para ver si funciona (para no hacerlo muy aburrido, voy a suponer que en cada CD existem solamente 2 músicas):
>
>
El script es fácil y funcional, me limito a añadir al final del archivo musicas el parámetro recibido. Vamos a incluir 3 álbumes para ver si funciona (y para no hacerlo muy aburrido, voy a suponer que en cada CD existem solamente 2 músicas):
 
$ musinc "album 3^Artista5~Musica5:Artista6~Musica5"
Line: 288 to 288
 album 2^Artista3~Musica3:Artista4~Musica4
Changed:
<
<
No está funcional como esperaba que quedase... podía haber quedado mejor. Los álbunes están fuera de orden, dificultando la búsqueda. Vamos a alterar nuestro script y después probarlo nuevamente:
>
>
No es tan funcional como esperaba que quedase... podía haber quedado mejor. Los álbumes están fuera de orden, dificultando la búsqueda. Vamos a alterar nuestro script y después a probarlo nuevamente:
 
$ cat musinc
Line: 299 to 299
 sort musicas -o musicas
Changed:
<
<
Vamos a cadastrar un álbum más:
>
>
Vamos a incluir un álbum más:
 
$ musinc "album 4^Artista7~Musica7:Artista8~Musica8"
Line: 315 to 315
 album 4^Artista7~Musica7:Artista8~Musica8
Changed:
<
<
Simplemente incluí una línea que clasifica el archivo musicas dándole salida en él mismo (para eso sirve la opción -o), después de que cada álbum fue incluído.
>
>
Simplemente incluí una línea que clasifica el archivo musicas dándole la salida sobre si mismo (para eso sirve la opción -o), después de que cada álbum fue incluído.
 
Changed:
<
<
Opa! Ahora está quedando bien y casi funcional. Pero atención, no se desespere! Esta no es la versión final. El programa quedará mucho mejor y más amigable, en una nueva versión que haremos después que aprendamos la adquirir los datos de la pantalla y a formatear la entrada
>
>
Opa! Ahora está quedando bien y casi funcional. Pero atención, no te desesperes! Esta no es la versión final. El programa quedará mucho mejor y más amigable, en una nueva versión que haremos después que aprendamos la adquirir los datos de la pantalla y a formatear la entrada
  Ejemplos
Changed:
<
<
Usar el comando cat para listar no es uma buena idea, vamos a hacer un programa llamado=muslist=, para listar un álbum cuyo nombre será pasado como un parámetro:
>
>
Usar el comando cat para listar no es una buena idea, vamos a hacer un programa llamado=muslist=, para listar un álbum cuyo nombre será pasado como un parámetro:
 
$ cat muslist
Line: 331 to 331
 grep $1 musicas
Changed:
<
<
Vamos a ejecutarlo, buscando el album 2. Como ya vimos anteriormente, para pasar la cadena de caracteres album 2 es necesario protegerla de la interpretación del Shell, así él no la interpreta como dos parámetros separados. Vamos a hacer de la siguiente forma:
>
>
Vamos a ejecutarlo, buscando el album 2. Como ya vimos anteriormente, para pasar la cadena de caracteres album 2 es necesario protegerla de la interpretación del Shell, así él no la interpreta como dos parámetros separados. Vamos a hacerlo de la siguiente forma:
 
$ muslist "álbum 2"
Line: 342 to 342
 musicas: album 4^Artista7~Musica7:Artista8~Musica8
Changed:
<
<
Que desorden! Donde está el error?. Tuve el cuidado de colocar el parámetro pasado entre comillas, para que el Shell no lo diviera en dos!
>
>
Que desorden! Donde está el error?. Tuve buen cuidado de colocar el parámetro pasado entre comillas, para que el Shell no lo diviera en dos!
 
Changed:
<
<
Si, pero nota ahora como el grep está siendo ejecutado:
>
>
Si, pero advierte ahora como el grep está siendo ejecutado:
       grep $1 musicas
Changed:
<
<
Aunque coloque álbum 2 entre comillas, para que fuera visto como un único parámetro, cuando el $1 fue pasado por el Shell para el comando grep, lo transformó en dos argumentos. Así, el contenido final de la línea que el comando grep ejecutó fue el siguiente:
>
>
Aunque coloque álbum 2 entre comillas, para que fuera visto como un único parámetro, cuando el $1 fue pasado por el Shell hacia el comando grep, lo transformó en dos argumentos. Así, el contenido final de la línea que el comando grep ejecutó fue el siguiente:
       grep album 2 musicas
Line: 358 to 358
  grep [arch1, arch2, ..., archn]
Changed:
<
<
el grep entendió que debería procurar la cadena de caracteres album en los archivos 2 y musicas, Por no existir el archivo 2 generó el error, y por encontrar la palabra album en todos los registros de musicas, listó todos ellos.
>
>
el grep entendió que debería recuperar la cadena de caracteres album en los archivos 2 y musicas, Al no existir el archivo 2 generó el error, y como encontro la palabra album en todos los registros de musicas, los listo todos.
 
Pinguim com placa de dica
Changed:
<
<
Siempre que la cadena de caracteres a ser pasada para el comando grep posea blancos o TAB, mismo que dentro de variables, colóquela siempre entre comillas para evitar que las palabras después del primer espacio en blanco o TAB sean interpretadas como nombres de archivos.
>
>
Siempre que la cadena de caracteres a ser pasada hacia el comando grep posea blancos o TAB, y lo mismo que dentro de variables, colóquela siempre entre comillas para evitar que las palabras después del primer espacio en blanco o TAB sean interpretadas como nombres de archivos.
 

Por otro lado, es mejor ignorar las mayúsculas y minúsculas en la búsqueda. Resolveríamos los dos problemas si el programa tuviera la siguiente forma:

Line: 374 to 374
 grep -i "$1" musicas
Changed:
<
<
En este caso, usamos la opción -i del grep, que como vimos, sirve para ignorar mayúsculas y minúsculas, y colocamos el $1 entre aspas, para que el grep continuara viendo la cadena de caracteres resultante de la expansión de la línea por el Shell como un único argumento de búsqueda.
>
>
En este caso, usamos la opción -i del grep, que como vimos, sirve para ignorar mayúsculas y minúsculas, y colocamos el $1 entre comillas, para que el grep continue viendo la cadena de caracteres resultante de la expansión de la línea por el Shell como un único argumento de búsqueda.
 
$ muslist "album 2" album2^Artista3~Musica3:Artista4~Musica4
Changed:
<
<
Ahora, note que el grep localiza la cadena buscada en cualquier lugar del registro, entonces de la forma que estamos haciendo, podemos buscar por álbum, por música, por intérprete o hasta por un pedazo de cualquiera de estos. Cuando conozcamos los comandos condicionales, montaremos una nueva versión de muslist que permitirá especificar por cual campo buscar.
>
>
Ahora, nota que el grep localiza la cadena buscada en cualquier lugar del registro, entonces de la forma que estamos lo haciendo, podemos buscar por álbum, por música, por intérprete o hasta por un pedazo de cualquiera de estos. Cuando conozcamos los comandos condicionales, montaremos una nueva versión de muslist que permitirá especificar por que campo buscar.
 
Changed:
<
<
Ahí me vas a decir:
>
>
Ahora me vas a decir:
      - Si, todo bien, pero es muy tedioso tener que colocar el argumento de búsqueda entre comillas cuando tengo que pasar el nombre del álbum. Esta forma no es nada amigable!
    - Tienes toda la razón, y es por eso que te voy a mostrar otra forma de hacer lo que me pediste:
Line: 402 to 402
  No te olvides que el problema del Shell no es si él puede o no hacer una determinada cosa. El problema es decidir cuál es la mejor forma de hacerla,ya que para realizar cualquier tarea, la cantidad de opciones es enorme.
Changed:
<
<
Ah! en un dia de verano fuiste a la playa, olvidaste el CD en el automóbil, y entonces aquel "solcito" de 40 grados dobló tu CD y ahora precisas de una herramienta para borrarlo del banco de datos? No hay ningún problema, vamos a desarrollar un script llamado musexc, para excluir estos CDs.
>
>
Recuerdas aquel dia de verano fuiste a la playa?, olvidaste el CD en el automóbil, y entonces aquel "solecito" de 40 grados dobló tu CD y ahora necesitas una herramienta para borrarlo del banco de datos. No hay ningún problema, vamos a desarrollar un script llamado musexc, para excluir estos CDs.
  Antes de desarrollar el programa te quiero presentar una opción bastante útil de la familia de comandos grep. Es la opción -v, que cuando es usada, lista todos los registros de la entrada, excepto el(los) localizado(s) por el comando. Veamos:
Line: 415 to 415
 album 4^Artista7~Musica7:Artista8~Musica8
Changed:
<
<
De acuerdo a lo te expliqué antes, el grep del exemplo listó todos los registros de músicas excepto los referentes al album 2, porque atendía al argumento del comando. Estamos entonces prontos para desarrollar el script para retirar aquél CD doblado de tu "CDteca". Él tiene la seguinte cara:
>
>
De acuerdo con lo que te expliqué antes, el grep del exemplo listó todos los registros de músicas excepto los referentes al album 2, porque atendía al argumento del comando. Estamos entonces preparados para desarrollar un script para retirar aquél CD doblado de tu "CDteca". Este script tiene la forma siguiente:
 
$ cat musexc
Line: 426 to 426
 mv -f /tmp/mus$$ musicas
Changed:
<
<
En la primera línea mandé para /tmp/mus$$ el archivo musicas, sin los registros que atendiesen la consulta hecha por el comando grep. En seguida, moví (que, en realidad, equivale a renombrarlo) /tmp/mus$$ por encima del antiguo musicas.
>
>
En la primera línea mandé hacia /tmp/mus$$ el archivo musicas, sin los registros que tuviesen la consulta hecha por el comando grep. En seguida, moví (que, en realidad, equivale a renombrarlo) /tmp/mus$$ al antiguo musicas.
  Usé el archivo /tmp/mus$$ como archivo de trabajo, porque como ya habia citado en el artículo anterior, el $$ contiene el PID (Process Identification o identificación del proceso) y de esta forma cada uno que edite el archivo musicas lo hará en un archivo de trabajo diferente, de esta forma evitamos choques en su uso.
Changed:
<
<
    - Y entonces, amigo, estos programas que hicimos hasta aquí están muy rústicos en virtud de la falta de herramientas que todavia tenemos. Pero están bien, en cuanto me tomo otro chopp, puedes ir para casa a praticar en los ejemplos dados porque, te prometo, llegaremos a desarrollar un sistema bien bonito para control de tus CDs.
>
>
    - Y entonces, amigo, estos programas que hicimos hasta aquí son muy rústicos en virtud de la falta de herramientas que todavia tenemos. Pero están bien, mientras me tomo otro "chopp", puedes ir para casa a praticar en los ejemplos dados porque, te prometo, llegaremos a desarrollar un sistema bien bonito para el control de tus CDs.
      - Cuando nos encontremos la próxima vez, te voy a enseñar como funcionan los comandos condicionales y mejoraremos otro poco estos scripts.
Changed:
<
<
    - Por hoy es suficiente! Ya hablé demás y preciso mojar la palabra porque estoy de garganta seca!
>
>
    - Por hoy es suficiente! Ya hablé demasiado y necesito mojar las palabras porque estoy con la garganta seca!
      - Mozo! Otro sin y espuma!
Changed:
<
<
Cualquer duda o falta de compañia para tomar un chopp 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.
>
>
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

Revision 813 Feb 2007 - JulioNeves

Line: 1 to 1
 

Conversa de Bar Parte II

Line: 437 to 437
  Cualquer duda o falta de compañia para tomar un chopp 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.
Changed:
<
<
Gracias y hasta la próxima!
>
>
Gracias y hasta la próxima
 

Revision 708 Jan 2007 - JulioNeves

Line: 1 to 1
 

Conversa de Bar Parte II

Line: 13 to 13
 

Me quedo con el grep, tú con la gripe

Changed:
<
<
Eso de la gripe es un sólo un decir! Simplemente un pretexto para pedir unas "Caipirinhas" (vea como prepararlas). Volviendo a nuestro tema, te dije que que el grep busca cadenas de caracteres dentro de una entrada definida, pero en realidad... que viene a ser una "entrada definida"? Bueno, existen varias formas de definir la entrada del comando grep. Veamos:
>
>
Eso de la gripe es un sólo un decir! Simplemente un pretexto para pedir unas "Caipirinhas" (o caipiriñas, el coctel oficial del carnaval brasileño wink - vea cómo prepararlas). Volviendo a nuestro tema, te dije que que el grep busca cadenas de caracteres dentro de una entrada definida, pero en realidad... que viene a ser una "entrada definida"? Bueno, existen varias formas de definir la entrada del comando grep. Veamos:
 Buscando en un archivo:

Revision 607 Jan 2007 - JulioNeves

Line: 1 to 1
 

Conversa de Bar Parte II

Line: 13 to 13
 

Me quedo con el grep, tú con la gripe

Changed:
<
<
Eso de la gripe es un sólo un decir! Simplemente un pretexto para pedir unas bebidas fuertes. Volviendo a nuestro tema, te dije que que el grep busca cadenas de caracteres dentro de una entrada definida, pero en realidad... que viene a ser una "entrada definida"? Bueno, existen varias formas de definir la entrada del comando grep. Veamos:
>
>
Eso de la gripe es un sólo un decir! Simplemente un pretexto para pedir unas "Caipirinhas" (vea como prepararlas). Volviendo a nuestro tema, te dije que que el grep busca cadenas de caracteres dentro de una entrada definida, pero en realidad... que viene a ser una "entrada definida"? Bueno, existen varias formas de definir la entrada del comando grep. Veamos:
 Buscando en un archivo:

Revision 507 Jan 2007 - JulioNeves

Line: 1 to 1
 

Conversa de Bar Parte II

Line: 9 to 9
     - Calma, lo que te dije hasta ahora, sirve como base para lo que ha de venir de aqui en adelante. Vamos a usar estas herramientas que vimos para montar programas estructurados, que el Shell te permite. Entonces tu verás por qué hasta en la TV ya hubo un programa llamado "El Shell es el Límite".
    - Para comenzar vamos a hablar de los comandos de la familia grep.
    - grep? No conozco ningún término en inglés con este nombre...
Changed:
<
<
    - Por supuesto, grep es un acrónimo Global Regular Expression Print, que usa expresiones regulares para buscar la ocurrencia de cadenas de caracteres en la entrada definida (si bien que hay una leyenda sobre como este comando fue bautizado: en el editor de textos "ed", el abuelo del "vim", el comando usado para buscar era g/_expresión regular_/p, en inglés g/_re_/p). Por hablar en expresiones regulares (o regexp), el portal Aurélio Marinho Jargas tiene todas las dicas en su página (inclusive tutoriales) que abordan el tema. Si estás realmente con ganas de aprender a programar en Shell, Perl, Python, ... debes leer estos artículos que te ayudarán a resolver lo que nos espera más adelante.
>
>
    - Por supuesto, grep es un acrónimo Global Regular Expression Print, que usa expresiones regulares para buscar la ocurrencia de cadenas de caracteres en la entrada definida (si bien que hay una leyenda sobre como este comando fue bautizado: en el editor de textos "ed", el abuelo del "vim", el comando usado para buscar era g/_expresión regular_/p, en inglés g/_re_/p). Por hablar en expresiones regulares (o regexp), el portal BULMA - Bisoños Usuarios de GNU/Linux de Mallorca y Alrededores tiene todas las dicas en su página (inclusive tutoriales) que abordan el tema. Si estás realmente con ganas de aprender a programar en Shell, Perl, Python, ... debes leer estos artículos que te ayudarán a resolver lo que nos espera más adelante.
 

Me quedo con el grep, tú con la gripe

Revision 403 Oct 2006 - Main.HumbertoPina

Line: 1 to 1
 

Conversa de Bar Parte II

Line: 162 to 162
 echo "3o. param -> $3"
Changed:
<
<
Vamos la ejecutarlo:
>
>
Vamos a ejecutarlo:
 
$ test pasando parámetros para verificar

Revision 301 Oct 2006 - JulioNeves

Line: 1 to 1
 

Conversa de Bar Parte II

Line: 354 to 354
  Como la sintáxis del grep es:

Changed:
<
<
    =grep [arch1, arch2, ..., archn]=
>
>
    grep <cadena de caracteres> [arch1, arch2, ..., archn]
  el grep entendió que debería procurar la cadena de caracteres album en los archivos 2 y musicas, Por no existir el archivo 2 generó el error, y por encontrar la palabra album en todos los registros de musicas, listó todos ellos.

Revision 201 Oct 2006 - Main.HumbertoPina

Line: 1 to 1
 

Conversa de Bar Parte II

Line: 190 to 190
  Las comillas no dejaron que el Shell viese el espacio en blanco entre las palabras y las consideró como un único parámetro.
Changed:
<
<

Observaciones sobre paramétros

>
>

Observaciones sobre parámetros

  Ya que estamos hablando en pasaje de parámetros observa bien lo siguiente:
Line: 223 to 223
 
$ test pasando parámetros para verificar El programa test recibió 4 parámetros
Changed:
<
<
1o. paarm -> pasando
>
>
1o. param -> pasando
 2o. param -> parámetros 3o. param -> para Todos de una sola "bolada": pasando parámetros para verificar
Line: 433 to 433
      - Por hoy es suficiente! Ya hablé demás y preciso mojar la palabra porque estoy de garganta seca!
    - Mozo! Otro sin y espuma!
Changed:
<
<
Cualquer duda o falta de compañia para tomar un chopp 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.
>
>
Cualquer duda o falta de compañia para tomar un chopp 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!

Revision 101 Oct 2006 - JulioNeves

Line: 1 to 1
Added:
>
>

Conversa de Bar Parte II

    - Mozo! Trae un "chopps" e dos "pastel". Mi amigo hoy no va a beber porque él finalmente está siendo presentado a un verdadero sistema operativo y todavia tiene mucha cosa para aprender!
    - Y entonces, amigo, está entendiendo todo lo que te expliqué hasta ahora?
    - Entendiendo estoy, pero no vi nada práctico en eso...
    - Calma, lo que te dije hasta ahora, sirve como base para lo que ha de venir de aqui en adelante. Vamos a usar estas herramientas que vimos para montar programas estructurados, que el Shell te permite. Entonces tu verás por qué hasta en la TV ya hubo un programa llamado "El Shell es el Límite".
    - Para comenzar vamos a hablar de los comandos de la familia grep.
    - grep? No conozco ningún término en inglés con este nombre...
    - Por supuesto, grep es un acrónimo Global Regular Expression Print, que usa expresiones regulares para buscar la ocurrencia de cadenas de caracteres en la entrada definida (si bien que hay una leyenda sobre como este comando fue bautizado: en el editor de textos "ed", el abuelo del "vim", el comando usado para buscar era g/_expresión regular_/p, en inglés g/_re_/p). Por hablar en expresiones regulares (o regexp), el portal Aurélio Marinho Jargas tiene todas las dicas en su página (inclusive tutoriales) que abordan el tema. Si estás realmente con ganas de aprender a programar en Shell, Perl, Python, ... debes leer estos artículos que te ayudarán a resolver lo que nos espera más adelante.

Me quedo con el grep, tú con la gripe

Eso de la gripe es un sólo un decir! Simplemente un pretexto para pedir unas bebidas fuertes. Volviendo a nuestro tema, te dije que que el grep busca cadenas de caracteres dentro de una entrada definida, pero en realidad... que viene a ser una "entrada definida"? Bueno, existen varias formas de definir la entrada del comando grep. Veamos: Buscando en un archivo:

$ grep rafael /etc/passwd

buscando en varios archivos:

$ grep grep *.sh

Buscando en la salida de un comando:

$ who | grep Pelegrino

En el 1º ejemplo, el más simple, busqué la palabra rafael en qualquier lugar del archivo /etc/passwd. Si quisiera buscarla como un login name, o sea, solamente en el inicio de los registros de este archivo, deberia hacer:

$ grep '^rafael' /etc/passwd

Y para que sirve este acento circunflejo y los apóstrofes? me vas a preguntar. El circunflejo (^), si hubieras leído los artículos anteriores sobre expresiones regulares que te dije, sabrías que sirven para limitar la búsqueda al inicio de cada línea, y los apóstrofes (') sirven para que el Shell no interprete este circunflejo, dejándolo pasar intacto para el comando grep.

Mira que bien! El grep acepta como entrada, la salida de otro comando redireccionado por un pipe (esto es muy común en Shell y es un tremendo acelerador de la ejecución de comandos, ya que actúa como si la salida de un programa fuera guardada en disco y el segundo programa leyera este archivo generado), de esta forma, en el 3º ejemplo, el comando who listó las personas "logadas" en la misma máquina que tú (no te olvides jamás: el Linux es multiusuario) y el grep fue usado para verificar si Pelegrino estaba trabajando o simplemente "haciendo sebo".

La familia grep

Este comando grep es muy conocido, pues es usado con mucha frecuencia. Algo que muchas personas desconocen es que existen tres comandos en la familia grep, que son:

  • grep
  • egrep
  • fgrep

Las principales diferencias entre los 3 son:

  • El grep puede o no, usar expresiones regulares simples, sin embargo en caso de no usarlas, el fgrep es mejor, por ser más rápido;
  • El egrep ("e" de extended, extendido) es muy poderoso en el uso de expresiones regulares. Por ser el más lento de la familia, solo debe ser usado cuando sea necesario la construcción de una expresión regular que no sea aceptada por el grep;
  • El fgrep ("f" de fast, rápido, o de "file", archivo) como el nombre dice, es el rapidito de la familia, ejecuta el servicio de forma muy veloz (a veces es cerca de 30% más rápido que el grep y 50% más que el egrep), sin embargo no permite el uso de expresiones regulares en la búsqueda.

Pinguim com placa de atenção (em espanhol) Todo lo que fue dicho arriba sobre la velocidad, solamente se aplica a la familia de comandos grep del Unix. En Linux el grep es siempre más veloz, ya que los otros dos (fgrep y egrep) son scripts en Shell que llamam al primero y, ya estoy adelantando, no me gusta nada esta solución.
    - Ahora que ya conoces las diferencias entre los miembros de la familia, dime: que te parecen los tres ejemplos que te dí antes de las explicaciones?
    - Me pareció que el fgrep resolvería tu problema de forma más veloz que el grep.
    - Perfecto! Estoy notando que estás bien atento! Estás entendiendo lo que te estoy explicando! Entonces vamos a ver más ejemplos, para aclarar de una vez por todas las diferencias del uso de los miembros de esta familia.

Ejemplos

Yo sé que en un archivo existe un texto hablando sobre Linux solo no sé si está escrito con L mayúsculo o l minúsculo. Puedo hacer la búsqueda de dos formas:

$ egrep (Linux | linux) archivo.txt

ou

$ grep [Ll]inux archivo.txt

En el primer caso, la expresión regular compleja "(Linux | linux)" usa los paréntesis para agrupar las opciones y la barra vertical (|) como un "o" lógico, o sea, estoy buscando Linux el linux.

En el segundo, la expresión regular [Ll]inux significa: comenzando por L o l seguido de inux. Como esta expresión es más simple, el grep consigue resolverla, por lo tanto creo mejor usar la segunda forma, ya que el egrep dejaría la búsqueda más lenta.

Otro ejemplo. Para listar todos los subdirectórios del directório corriente, basta hacer:

$ ls -l | grep '^d' drwxr-xr-x 3 root root 4096 Dec 18 2000 doc drwxr-xr-x 11 root root 4096 Jul 13 18:58 freeciv drwxr-xr-x 3 root root 4096 Oct 17 2000 gimp drwxr-xr-x 3 root root 4096 Aug 8 2000 gnome drwxr-xr-x 2 root root 4096 Aug 8 2000 idl drwxrwxr-x 14 root root 4096 Jul 13 18:58 locale drwxrwxr-x 12 root root 4096 Jan 14 2000 lyx drwxrwxr-x 3 root root 4096 Jan 17 2000 pixmaps drwxr-xr-x 3 root root 4096 Jul 2 20:30 scribus drwxrwxr-x 3 root root 4096 Jan 17 2000 sounds drwxr-xr-x 3 root root 4096 Dec 18 2000 xine

En el ejemplo que acabamos de ver, el circunflejo (^) sirvió para limitar la pesquisa a la primera posición de la salida del ls detallado. los apóstrofes fueron colocados para que el Shell no "viera" el circunflejo (^).

Vamos a ver otro. Sabemos que las cuatro primeras posiciones posibles de un ls -l de un archivo común (archivo común! No directório, ni link, ni ...) deben ser:

Posición  1ª   2ª   3ª   4ª 
      -
 Valores Posibles  - r w x
  - -   s (suid) 

Así, para descubrir todos los archivos ejecutables en un determinado directório deberia hacer:

$ ls -la | egrep '^-..(x|s)' -rwxr-xr-x 1 root root 2875 Jun 18 19:38 rc -rwxr-xr-x 1 root root 857 Aug 9 22:03 rc.local -rwxr-xr-x 1 root root 18453 Jul 6 17:28 rc.sysinit

Donde nuevamente usamos el circunflejo (^) para limitar la búsqueda al inicio de cada línea, entonces las líneas listadas serán las que comiezan por un trazo (-), seguido de cualquier cosa (el punto cuando usado como una expresión regular significa cualquier cosa), nuevamente seguido de cualquer cosa, y siguiendo un x o un s.

Obtendríamos el mismo resultado si hicieramos:

$ ls -la | grep '^-..[xs]'

y agilizaríamos la búsqueda.

Vamos a montar una "CDteca"

Vamos a comenzar a desarrollar programas, me parece que montar un banco de datos de músicas es muy útil y didático (y además práctico, en estos tiempos de downloads de mp3 y "quemadores" de CDs). No te olvides que, de la misma forma que vamos desarrollar una cantidad de programas para organizar tus CDs de música, con pequeñas adaptaciones, puedes hacer lo mismo con los CDs de software que vienen con la Linux Magazine y otros que compres o quemes, si disponibilizas este banco de software para todos los que trabajan contigo (el Linux es multiusuario, y como tal debe ser explotado), ganarás muchos puntos con tu adorado jefe.

    - Un momento! De donde voy la recibir los datos de los CDs?
    - Inicialmente, te voy a mostrar como tu programa puede recibir parámetros de quién lo esté ejecutando y en breve, te enseñaré a leer los datos por la pantalla o de un archivo.

Pasando parámetros

El visual del archivo musicas será el siguiente:

     nombre del álbum^intérprete1~nombre de la música1:..:intérprete~nombre de la música

o sea, el nombre del álbum será separado por un circunflejo (^) del resto del registro, que está formado por diversos grupos compuestos por el intérprete de cada música del CD y la respectiva música interpretada. Estos grupos son separados entre sí por dos-puntos (:) e internamente, el intérprete será separado por un til (~) del nombre de la música.

Escribiré un programa llamado musinc, que incluirá registros en mi archivo músicas. Pasaré el contenido de cada álbum como parâmetro en la llamada del programa de la siguiente forma:

$ musinc "álbum^interprete~música:interprete~música:..."

De esta forma el programa musinc estará recibiendo los datos de cada álbum como si fuera una variable. La única diferencia entre un parámetro recibido y una variable es que los primeros reciben nombres numéricos (nombre numérico suena algo raro, no?). Lo que quise decir es que sus nombres son formados por un y solamente un algarismo), el sea $1, $2, $3, ..., $9. Vamos, antes de todo, hacer un test:

Ejemplos

$ cat test #!/bin/bash # Programa para verificar el pasaje de parámetros echo "1o. param -> $1" echo "2o. param -> $2" echo "3o. param -> $3"

Vamos la ejecutarlo:

$ test pasando parámetros para verificar bash: test: cannot execute

Opa! Me olvidé de hacerlo ejecutable. Voy a hacerlo de forma que permita que todos puedan ejecutarlo y en seguida voy a testarlo:

$ chmod 755 test $ test pasando parámetros para verificar 1o. param -> pasando 2o. param -> parámetros 3o. param -> para

Repare que la palabra verificar, que sería el cuarto parámetro, no fue listada. Esto sucedió justamente porque el programa test solo listaba los tres primeros parámetros. Vamos ejecutarlo de otra forma:

$ test "pasando parámetros" para verificar 1o. param -> pasando parámetros 2o. param -> para 3o. param -> verificar

Las comillas no dejaron que el Shell viese el espacio en blanco entre las palabras y las consideró como un único parámetro.

Observaciones sobre paramétros

Ya que estamos hablando en pasaje de parámetros observa bien lo siguiente:

Significado de las Principales Variables Referentes a los Parámetros
$*   Contiene el conjunto de todos los parámetros (muy parecido con $@)  
  Variable     Significado  
$0   Contiene el nombre del programa  
$#   Contiene la cuantidad de parámetros pasados  

Ejemplos

Vamos a alterar el programa test para usar las variables que acabamos de ver. Vamos hacerlo así:

$ cat test #!/bin/bash # Programa para verifivar el pasaje de parámetros (2a. Versao) echo El programa $0 recibió $# parámetros echo "1o. param -> $1" echo "2o. param -> $2" echo "3o. param -> $3" echo Todos de una sola \"bolada\": $*

Repare que antes de las comillas usé una barra invertida para esconderlas de la interpretación del Shell (si no usase las contrabarras las comillas no aparecerian). Vamos a ejecutarlo:

$ test pasando parámetros para verificar El programa test recibió 4 parámetros 1o. paarm -> pasando 2o. param -> parámetros 3o. param -> para Todos de una sola "bolada": pasando parámetros para verificar

Como ya dije, los parámetros reciben números de 1 a 9, pero eso no significa que no puedo usar más de 9 parámetros, significa solamente que solo puedo direccionar 9. Vamos a verificar eso:

Ejemplo:

$ cat test #!/bin/bash # Programa para verificar el pasaje de parámetros (3a. Versión) echo El programa $0 recebió $# parámetros echo "11o. param -> $11" shift echo "2o. param -> $1" shift 2 echo "4o. Param -> $1"

Vamos a ejecutarlo:

$ test pasando parámetros para verificar El programa test recebió 4 parámetros que son: 11o. param -> pasando1 2o. param -> parámetros 4o. param -> verificar

Dos cosas muy interesantes en este script:

  1. Para mostrar que los nombres de los parámetros varían de $1 a $9 hice un echo $11 y que pasó? El Shell interpretó como que era $1 seguido del algarismo 1 y listó pasando1;
  2. El comando shift cuya sintáxis es shift n, pudiendo el n asumir cualquier valor numérico (sin embargo su default es 1, como en el ejemplo dado), desprecia los n primeros parámetros, devolviendo el parámetro de orden n+1, el primero o sea, el $1.

Bueno, ahora que ya sabes más sobre pasaje de parámetros que yo mismo, vamos a voltar a nuestra "CDteca" para hacer el script para incluir los CDs en mi banco llamado musicas. El programa es muy simple (como todo en Shell) y voy a listarlo para que lo veas:

Ejemplos

$ cat musinc #!/bin/bash # Incluye CDs (versión 1) # echo $1 >> musicas

El script es fácil y funcional, limítome a anexar al fin del archivo musicas el parámetro recibido. Vamos a incluir 3 álbunes para ver si funciona (para no hacerlo muy aburrido, voy a suponer que en cada CD existem solamente 2 músicas):

$ musinc "album 3^Artista5~Musica5:Artista6~Musica5" $ musinc "album 1^Artista1~Musica1:Artista2~Musica2" $ musinc "album 2^Artista3~Musica3:Artista4~Musica4"

Muestro ahora el contenido de musicas.

$ cat musicas album 3^Artista5~Musica5:Artista6~Musica6 album 1^Artista1~Musica1:Artista2~Musica2 album 2^Artista3~Musica3:Artista4~Musica4

No está funcional como esperaba que quedase... podía haber quedado mejor. Los álbunes están fuera de orden, dificultando la búsqueda. Vamos a alterar nuestro script y después probarlo nuevamente:

$ cat musinc #!/bin/bash # Incluye CDs (versión 2) # echo $1 >> musicas sort musicas -o musicas

Vamos a cadastrar un álbum más:

$ musinc "album 4^Artista7~Musica7:Artista8~Musica8"

Ahora vamos a ver lo que pasó con el archivo musicas:

$ cat musicas album 1^Artista1~Musica1:Artista2~Musica2 album 2^Artista3~Musica3:Artista4~Musica4 album 3^Artista5~Musica5:Artista6~Musica5 album 4^Artista7~Musica7:Artista8~Musica8

Simplemente incluí una línea que clasifica el archivo musicas dándole salida en él mismo (para eso sirve la opción -o), después de que cada álbum fue incluído.

Opa! Ahora está quedando bien y casi funcional. Pero atención, no se desespere! Esta no es la versión final. El programa quedará mucho mejor y más amigable, en una nueva versión que haremos después que aprendamos la adquirir los datos de la pantalla y a formatear la entrada

Ejemplos

Usar el comando cat para listar no es uma buena idea, vamos a hacer un programa llamado=muslist=, para listar un álbum cuyo nombre será pasado como un parámetro:

$ cat muslist #!/bin/bash # Consulta CDs (versión 1) # grep $1 musicas

Vamos a ejecutarlo, buscando el album 2. Como ya vimos anteriormente, para pasar la cadena de caracteres album 2 es necesario protegerla de la interpretación del Shell, así él no la interpreta como dos parámetros separados. Vamos a hacer de la siguiente forma:

$ muslist "álbum 2" grep: can't open 2 musicas: album 1^Artista1~Musica1:Artista2~Musica2 musicas: album 2^Artista3~Musica3:Artista4~Musica4 musicas: album 3^Artista5~Musica5:Artista6~Musica6 musicas: album 4^Artista7~Musica7:Artista8~Musica8

Que desorden! Donde está el error?. Tuve el cuidado de colocar el parámetro pasado entre comillas, para que el Shell no lo diviera en dos!

Si, pero nota ahora como el grep está siendo ejecutado:

     grep $1 musicas

Aunque coloque álbum 2 entre comillas, para que fuera visto como un único parámetro, cuando el $1 fue pasado por el Shell para el comando grep, lo transformó en dos argumentos. Así, el contenido final de la línea que el comando grep ejecutó fue el siguiente:

     grep album 2 musicas

Como la sintáxis del grep es:

    =grep [arch1, arch2, ..., archn]=

el grep entendió que debería procurar la cadena de caracteres album en los archivos 2 y musicas, Por no existir el archivo 2 generó el error, y por encontrar la palabra album en todos los registros de musicas, listó todos ellos.

Pinguim com placa de dica Siempre que la cadena de caracteres a ser pasada para el comando grep posea blancos o TAB, mismo que dentro de variables, colóquela siempre entre comillas para evitar que las palabras después del primer espacio en blanco o TAB sean interpretadas como nombres de archivos.

Por otro lado, es mejor ignorar las mayúsculas y minúsculas en la búsqueda. Resolveríamos los dos problemas si el programa tuviera la siguiente forma:

$ cat muslist #!/bin/bash # Consulta CDs (versión 2) # grep -i "$1" musicas

En este caso, usamos la opción -i del grep, que como vimos, sirve para ignorar mayúsculas y minúsculas, y colocamos el $1 entre aspas, para que el grep continuara viendo la cadena de caracteres resultante de la expansión de la línea por el Shell como un único argumento de búsqueda.

$ muslist "album 2" album2^Artista3~Musica3:Artista4~Musica4

Ahora, note que el grep localiza la cadena buscada en cualquier lugar del registro, entonces de la forma que estamos haciendo, podemos buscar por álbum, por música, por intérprete o hasta por un pedazo de cualquiera de estos. Cuando conozcamos los comandos condicionales, montaremos una nueva versión de muslist que permitirá especificar por cual campo buscar.

Ahí me vas a decir:

    - Si, todo bien, pero es muy tedioso tener que colocar el argumento de búsqueda entre comillas cuando tengo que pasar el nombre del álbum. Esta forma no es nada amigable!
    - Tienes toda la razón, y es por eso que te voy a mostrar otra forma de hacer lo que me pediste:

$ cat muslist #!/bin/bash # Consulta CDs (versión 3) # grep -i "$*" musicas $ muslist album 2 album 2^Artista3~Musica3:Artista4~Musica4

De esta forma, el $*, que significa todos los parámetros, será substituído por la cadena album 2 (de acuerdo con el ejemplo anterior), haciendo lo que tu querias.

No te olvides que el problema del Shell no es si él puede o no hacer una determinada cosa. El problema es decidir cuál es la mejor forma de hacerla,ya que para realizar cualquier tarea, la cantidad de opciones es enorme.

Ah! en un dia de verano fuiste a la playa, olvidaste el CD en el automóbil, y entonces aquel "solcito" de 40 grados dobló tu CD y ahora precisas de una herramienta para borrarlo del banco de datos? No hay ningún problema, vamos a desarrollar un script llamado musexc, para excluir estos CDs.

Antes de desarrollar el programa te quiero presentar una opción bastante útil de la familia de comandos grep. Es la opción -v, que cuando es usada, lista todos los registros de la entrada, excepto el(los) localizado(s) por el comando. Veamos:

Ejemplos

$ grep -v "album 2" musicas album 1^Artista1~Musica1:Artista2~Musica2 album 3^Artista5~Musica5:Artista6~Musica6 album 4^Artista7~Musica7:Artista8~Musica8

De acuerdo a lo te expliqué antes, el grep del exemplo listó todos los registros de músicas excepto los referentes al album 2, porque atendía al argumento del comando. Estamos entonces prontos para desarrollar el script para retirar aquél CD doblado de tu "CDteca". Él tiene la seguinte cara:

$ cat musexc #!/bin/bash # Borra CDs (versión 1) # grep -v "$1" musicas > /tmp/mus$$ mv -f /tmp/mus$$ musicas

En la primera línea mandé para /tmp/mus$$ el archivo musicas, sin los registros que atendiesen la consulta hecha por el comando grep. En seguida, moví (que, en realidad, equivale a renombrarlo) /tmp/mus$$ por encima del antiguo musicas.

Usé el archivo /tmp/mus$$ como archivo de trabajo, porque como ya habia citado en el artículo anterior, el $$ contiene el PID (Process Identification o identificación del proceso) y de esta forma cada uno que edite el archivo musicas lo hará en un archivo de trabajo diferente, de esta forma evitamos choques en su uso.

    - Y entonces, amigo, estos programas que hicimos hasta aquí están muy rústicos en virtud de la falta de herramientas que todavia tenemos. Pero están bien, en cuanto me tomo otro chopp, puedes ir para casa a praticar en los ejemplos dados porque, te prometo, llegaremos a desarrollar un sistema bien bonito para control de tus CDs.
    - Cuando nos encontremos la próxima vez, te voy a enseñar como funcionan los comandos condicionales y mejoraremos otro poco estos scripts.
    - Por hoy es suficiente! Ya hablé demás y preciso mojar la palabra porque estoy de garganta seca!
    - Mozo! Otro sin y espuma!

Cualquer duda o falta de compañia para tomar un chopp 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 - 13 Sep 2006

 
This site is powered by FoswikiCopyright © 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