  Programacin en BASH - COMO de introduccin
  Mike G (mikkey) disponible en dynamo.com.ar
  Traducido por Gabriel Rodrguez Alberich chewie@asef.us.es

  jueves, 27 de julio de 2000, a las 09:36:18 ART

  Este artculo pretende ayudarle a comenzar a programar shell scripts a
  un nivel bsico/intermedio. No pretende ser un documento avanzado (vea
  el ttulo). NO soy un experto ni un gur de la programacin en shell.
  Decid escribir esto porque aprender mucho con ello y puede serle
  til a otras personas. Cualquier aportacin ser apreciada, especial
  mente en forma de parche :)

  ______________________________________________________________________

  ndice general



  1. Introduccin
     1.1 Obteniendo la ltima versin
     1.2 Requisitos
     1.3 Usos de este documento

  2. Scripts muy sencillos
     2.1 Tpico script `hola mundo'
     2.2 Un script de copia de seguridad muy simple

  3. Todo sobre redireccin
     3.1 Teora y referencia rpida
     3.2 Ejemplo: stdout a un fichero
     3.3 Ejemplo: stderr a un fichero
     3.4 Ejemplo: stdout a stderr
     3.5 Ejemplo: stderr a stdout
     3.6 Ejemplo: stderr y stdout a un fichero

  4. Tuberas
     4.1 Qu son y por qu querr utilizarlas
     4.2 Ejemplo: una tubera sencilla con sed
     4.3 Ejemplo: una alternativa a ls -l *.txt

  5. Variables
     5.1 Ejemplo: Hola Mundo! utilizando variables
     5.2 Ejemplo: Un script de copia de seguridad muy simple (algo mejor)
     5.3 Variables locales

  6. Estructuras Condicionales
     6.1 Pura teora
     6.2 Ejemplo: Ejemplo bsico de condicional if .. then
     6.3 Ejemplo: Ejemplo bsico de condicional if .. then ... else
     6.4 Ejemplo: Condicionales con variables
     6.5 Ejemplo: comprobando si existe un fichero

  7. Los bucles for, while y until
     7.1 Por ejemplo
     7.2 for tipo-C
     7.3 Ejemplo de while
     7.4 Ejemplo de until

  8. Funciones
     8.1 Ejemplo de funciones
     8.2 Ejemplo de funciones con parmetros

  9. Interfaces de usuario
     9.1 Utilizando select para hacer mens sencillos
     9.2 Utilizando la lnea de comandos

  10. Miscelnea
     10.1 Leyendo informacin del usuario
     10.2 Evaluacin aritmtica
     10.3 Encontrando el bash
     10.4 Obteniendo el valor devuelto por un programa
     10.5 Capurando la salida de un comando

  11. Tablas
     11.1 Operadores de comparacin de cadenas
     11.2 Ejemplo de comparacin de cadenas
     11.3 Operadores aritmticos
     11.4 Operadores relacionales aritmticos
     11.5 Comandos tiles

  12. Ms scripts
     12.1 Aplicando un comando a todos los ficheros de un directorio.
     12.2 Ejemplo: Un script de copia de seguridad muy simple (algo mejor)
     12.3 Re-nombrador de ficheros
     12.4 Re-nombrador de ficheros (sencillo)

  13. Cuando algo va mal (depuracin)
     13.1 Maneras de llamar a BASH

  14. Sobre el documento
     14.1 (sin) Garanta
     14.2 Traducciones
     14.3 Agradecimientos
     14.4 Historia
     14.5 Ms recursos


  ______________________________________________________________________

  11..  IInnttrroodduucccciinn

  11..11..  OObbtteenniieennddoo llaa llttiimmaa vveerrssiinn

  http://www.linuxdoc.org/HOWTO/Bash-Prog-Intro-HOWTO.html



  11..22..  RReeqquuiissiittooss

  Le ser til tener una cierta familiaridad con la lnea de comandos de
  GNU/Linux y con los conceptos bsicos de la programacin.  Aunque esto
  no es una introduccin a la programacin, explica (o al menos lo
  intenta) muchos conceptos bsicos.



  11..33..  UUssooss ddee eessttee ddooccuummeennttoo

  Este documento intenta ser til en las siguientes situaciones

    Si tiene alguna idea de programacin y quiere empezar a programar
     algunos shell scripts.

    Si tiene una idea vaga de programar en shell y quiere algn tipo de
     referencia.

    Si quiere ver algunos scripts y comentarios para empezar a escribir
     los suyos propios.

    Si est migrando desde DOS/Windows (o ya lo ha hecho) y quiere
     hacer procesos "por lotes".

    Si es un completo novato y lee todo COMO disponible.

  22..  SSccrriippttss mmuuyy sseenncciillllooss

  Este COMO tratar de darle algunos consejos sobre la programacin de
  shell scripts, basndose profundamente en ejemplos.

  En esta seccin encontrar varios scripts pequeos que
  esperanzadamente le ayudarn a entender algunas tcnicas.


  22..11..  TTppiiccoo ssccrriipptt ``hhoollaa mmuunnddoo''



            #!/bin/bash
            echo Hola Mundo



  Este script tiene slo dos lneas.  La primera le indica al sistema
  qu programa usar para ejecutar el fichero.

  La segunda lnea es la nica accin realizada por este script, que
  imprime 'Hola Mundo' en la terminal.

  Si le sale algo como _._/_h_e_l_l_o_._s_h_: _C_o_m_a_n_d_o _d_e_s_c_o_n_o_c_i_d_o_., probablemente
  la primera lnea, '#!/bin/bash', est mal. Ejecute whereis bash, o vea
  'encontrando el bash' para saber cmo debe escribir esta lnea.

  22..22..  UUnn ssccrriipptt ddee ccooppiiaa ddee sseegguurriiddaadd mmuuyy ssiimmppllee



               #!/bin/bash
               tar -cZf /var/my-backup.tgz /home/yo/



  En este script, en vez de imprimir un mensaje en la terminal, creamos
  un tar-ball del directorio home de un usuario. Esto NO pretende ser un
  script til; ms tarde se ofrece un script de copia de seguridad ms
  til.

  33..  TTooddoo ssoobbrree rreeddiirreecccciinn

  33..11..  TTeeoorraa yy rreeffeerreenncciiaa rrppiiddaa

  Existen 3 descriptores de ficheros: stdin, stdout y stderr
  (std=estndar).


  Bsicamente, usted puede:

  1. redirigir stdout a un fichero

  2. redirigir stderr a un fichero

  3. redirigir stdout a stderr

  4. redirigir stderr a stdout

  5. redirigir stderr y stdout a un fichero

  6. redirigir stderr y stdout a stdout

  7. redirigir stderr y stdout a stderr

     El nmero 1 'representa' a stdout, y 2 a stderr.

  Una pequea nota para ver todo esto: con el comando less puede
  visualizar stdout (que permanecer en el bfer) y stderr, que se
  imprimir en la pantalla, pero ser borrado si intenta leer el bfer.


  33..22..  EEjjeemmpplloo:: ssttddoouutt aa uunn ffiicchheerroo

  Esto har que la salida de un programa se escriba en un fichero.


               ls -l > ls-l.txt



  En este caso, se crear un fichero llamado 'ls-l.txt' que contendr lo
  que se vera en la pantalla si escribiese el comando 'ls -l' y lo eje
  cutase.

  33..33..  EEjjeemmpplloo:: ssttddeerrrr aa uunn ffiicchheerroo

  Esto har que la salida stderr de un programa se escriba en un
  fichero.


               grep da * 2> errores-de-grep.txt



  En este caso, se crear un fichero llamado 'errores-de-grep.txt' que
  contendr la parte stderr de la salida que dara el comando 'grep da
  *'.

  33..44..  EEjjeemmpplloo:: ssttddoouutt aa ssttddeerrrr

  Esto har que la salida stdout de un programa se escriba en el mismo
  descriptor de fichero que stderr.


               grep da * 1>&2



  En este caso, la parte stdout del comando se enva a stderr; puede
  observar eso de varias maneras.

  33..55..  EEjjeemmpplloo:: ssttddeerrrr aa ssttddoouutt

  Esto har que la salida stderr de un programa se escriba en el mismo
  descriptor de fichero que stdout.


               grep * 2>&1



  En este caso, la parte stderr del comando se enva a stdout. Si hace
  una tubera con less, ver que las lneas que normalmente 'desapare
  cen' (al ser escritas en stderr), ahora permanecen (porque estn en el
  stdout).



  33..66..  EEjjeemmpplloo:: ssttddeerrrr yy ssttddoouutt aa uunn ffiicchheerroo

  Esto colocar toda la salida de un programa en un fichero. A veces,
  esto es conveniente en las entradas del cron, si quiere que un comando
  se ejecute en absoluto silencio.


               rm -f $(find / -name core) &> /dev/null



  Esto (pensando en la entrada del cron) eliminar todo archivo llamado
  `core' en cualquier directorio. Tenga en cuenta que tiene que estar
  muy seguro de lo que hace un comando si le va a eliminar la salida.

  44..  TTuubbeerraass

  Esta seccin explica de una manera muy sencilla y prctica cmo
  utilizar tuberas, y por qu querra utilizarlas.


  44..11..  QQuu ssoonn yy ppoorr qquu qquueerrrr uuttiilliizzaarrllaass

  Las tuberas le permiten utilizar (muy sencillo, insisto) la salida de
  un programa como la entrada de otro.

  44..22..  EEjjeemmpplloo:: uunnaa ttuubbeerraa sseenncciillllaa ccoonn sseedd

  sta es una manera muy sencilla de utilizar tuberas.


               ls -l | sed -e "s/[aeio]/u/g"



  En este caso, ocurre lo siguiente: primero se ejecuta el comando ls
  -l, y luego su salida, en vez de imprimirse en la pantalla, se enva
  (entuba) al programa sed, que imprime su salida correspondiente.

  44..33..  EEjjeemmpplloo:: uunnaa aalltteerrnnaattiivvaa aa llss --ll **..ttxxtt

  Probablemente sta es una manera ms difcil de hacer un ls -l *.txt,
  pero se muestra para ilustrar el funcionamiento de las tuberas, no
  para resolver ese dilema.


               ls -l | grep "\.txt$"



  En este caso, la salida del programa ls -l se enva al programa grep,
  que imprimir las lneas que concuerden con la regex (expresin regu
  lar) "\.txt$".

  55..  VVaarriiaabblleess

  Puede usar variables como en cualquier otro lenguaje de programacin.
  No existen tipos de datos. Una variable de bash puede contener un
  nmero, un caracter o una cadena de caracteres.

  No necesita declarar una variable. Se crear slo con asignarle un
  valor a su referencia.



  55..11..  EEjjeemmpplloo:: HHoollaa MMuunnddoo!! uuttiilliizzaannddoo vvaarriiaabblleess



                   #!/bin/bash
                   CAD="Hola Mundo!"
                   echo $CAD



  La segunda lnea crea una variable llamada STR y le asigna la cadena
  "Hola Mundo!". Luego se recupera el VALOR de esta variable ponindole
  un '$' al principio. Por favor, tenga en cuenta (intntelo!)  que si
  no usa el signo '$', la salida del programa ser diferente, y
  probablemente no sea lo que usted quera.

  55..22..  EEjjeemmpplloo:: UUnn ssccrriipptt ddee ccooppiiaa ddee sseegguurriiddaadd mmuuyy ssiimmppllee ((aallggoo mmeejjoorr))



                  #!/bin/bash
                  OF=/var/mi-backup-$(date +%Y%m%d).tgz
                  tar -cZf $OF /home/yo/



  Este script introduce algo nuevo. Antes que nada, debera
  familiarizarse con la creacin y asignacin de variable de la lnea 2.
  Fjese en la expresin '$(date +%Y%m%d)'. Si ejecuta el script se dar
  cuenta de que ejecuta el comando que hay dentro de los parntesis,
  capturando su salida.


  Tenga en cuenta que en este script, el fichero de salida ser distinto
  cada da, debido al formato pasado al comando date (+%Y%m%d).  Puede
  cambiar esto especificando un formato diferente.

  Algunos ejemplos ms:

  echo ls

  echo $(ls)

  55..33..  VVaarriiaabblleess llooccaalleess

  Las variables locales pueden crearse utilizando la palabra clave
  _l_o_c_a_l.



                  #!/bin/bash
                  HOLA=Hola
                  function hola {
                          local HOLA=Mundo
                          echo $HOLA
                  }
                  echo $HOLA
                  hola
                  echo $HOLA



  Este ejemplo debera bastar para mostrarle el uso de una variable
  local.

  66..  EEssttrruuccttuurraass CCoonnddiicciioonnaalleess

  Las estructuras condicionales le permiten decidir si se realiza una
  accin o no; esta decisin se toma evaluando una expresin.


  66..11..  PPuurraa tteeoorraa

  Los condicionales tienen muchas formas. La ms bsica es: iiff _e_x_p_r_e_s_i__n
  tthheenn _s_e_n_t_e_n_c_i_a donde 'sentencia' slo se ejecuta si 'expresin' se
  evala como verdadera. '2<1' es una expresin que se evala falsa,
  mientras que '2>1' se evala verdadera.

  Los condicionales tienen otras formas, como: iiff _e_x_p_r_e_s_i__n tthheenn
  _s_e_n_t_e_n_c_i_a_1 eellssee _s_e_n_t_e_n_c_i_a_2.  Aqu 'sentencia1' se ejecuta si
  'expresin' es verdadera. De otra manera se ejecuta 'sentencia2'.

  Otra forma ms de condicional es: iiff _e_x_p_r_e_s_i__n_1 tthheenn _s_e_n_t_e_n_c_i_a_1 eellssee
  iiff _e_x_p_r_e_s_i__n_2 tthheenn _s_e_n_t_e_n_c_i_a_2 eellssee _s_e_n_t_e_n_c_i_a_3.  En esta forma slo se
  aade "ELSE IF 'expresin2' THEN 'sentencia2'", que hace que
  sentencia2 se ejecute si expresin2 se evala verdadera.  El resto es
  como puede imaginarse (vanse las formas anteriores).

  Unas palabras sobre la sintaxis:

  La base de las construcciones 'if' es sta:

  if [expresin];

  then

  cdigo si 'expresin' es verdadera.

  fi

  66..22..  EEjjeemmpplloo:: EEjjeemmpplloo bbssiiccoo ddee ccoonnddiicciioonnaall iiff .... tthheenn



                   #!/bin/bash
                   if [ "petete" = "petete" ]; then
                      echo expresin evaluada como verdadera
                   fi



  El cdigo que se ejecutar si la expresin entre corchetes es
  verdadera se encuentra entre la palabra 'then' y la palabra 'fi', que
  indica el final del cdigo ejecutado condicionalmente.

  66..33..  EEjjeemmpplloo:: EEjjeemmpplloo bbssiiccoo ddee ccoonnddiicciioonnaall iiff .... tthheenn ...... eellssee



                   #!/bin/bash     if [ "petete" = "petete" ]; then
                      echo expresin evaluada como verdadera
                   else
                      echo expresin evaluada como falsa
                   fi



  66..44..  EEjjeemmpplloo:: CCoonnddiicciioonnaalleess ccoonn vvaarriiaabblleess



                   #!/bin/bash
                   T1="petete"
                   T2="peteto"
                   if [ "$T1" = "$T2" ]; then
                       echo expresin evaluada como verdadera
                   else
                       echo expresin evaluada como falsa
                   fi



  66..55..  EEjjeemmpplloo:: ccoommpprroobbaannddoo ssii eexxiissttee uunn ffiicchheerroo

  un agradecimiento ms a mike


                   #!/bin/bash
                   FILE=~/.basrc
                   if [ -f $FILE ]; then
                       echo el fichero $FILE existe
                   else
                       echo fichero no encontrado
                   fi
                   if [ 'test -f $FILE']



  77..  LLooss bbuucclleess ffoorr,, wwhhiillee yy uunnttiill

  En esta seccin se encontrar con los bucles for, while y until.

  El bucle ffoorr es distinto a los de otros lenguajes de programacin.
  Bsicamente, le permite iterar sobre una serie de `palabras'
  contenidas dentro de una cadena.

  El bucle wwhhiillee ejecuta un trozo de cdico si la expresin de control
  es verdadera, y slo se para cuando es falsa (o se encuentra una
  interrupcin explcita dentro del cdigo en ejecucin).

  El bucle uunnttiill es casi idntico al bucle loop, excepto en que el
  cdigo se ejecuta mientras la expresin de control se evale como
  falsa.

  Si sospecha que while y until son demasiado parecidos, est en lo
  cierto.


  77..11..  PPoorr eejjeemmpplloo



               #!/bin/bash
               for i in $( ls ); do
                   echo item: $i
               done



  En la segunda lnea declaramos i como la variable que recibir los
  diferentes valores contenidos en $( ls ).

  La tercera lnea podra ser ms larga o podra haber ms lneas antes
  del done (4).

  `done' (4) indica que el cdigo que ha utilizado el valor de $i ha
  acabado e $i puede tomar el nuevo valor.

  Este script no tiene mucho sentido, pero una manera ms til de usar
  el bucle for sera hacer que concordasen slo ciertos ficheros en el
  ejemplo anterior.


  77..22..  ffoorr ttiippoo--CC

  Fiesh sugiri aadir esta forma de bucle. Es un bucle for ms parecido
  al for de C/perl...


               #!/bin/bash
               for i in `seq 1 10`;
               do
                       echo $i
               done



  77..33..  EEjjeemmpplloo ddee wwhhiillee



           #!/bin/bash
           CONTADOR=0
           while [  $CONTADOR -lt 10 ]; do
               echo El contador es $CONTADOR
               let CONTADOR=CONTADOR+1
           done



  Este script 'emula' la conocida (C, Pascal, perl, etc) estructura
  `for'.

  77..44..  EEjjeemmpplloo ddee uunnttiill



                #!/bin/bash
                CONTADOR=20
                until [  $CONTADOR -lt 10 ]; do
                    echo CONTADOR $CONTADOR
                    let CONTADOR-=1
                done



  88..  FFuunncciioonneess

  Como en casi todo lenguaje de programacin, puede utilizar funciones
  para agrupar trozos de cdigo de una manera ms lgica, o practicar el
  divino arte de la recursin.

  Declarar una funcin es slo cuestin de escribir function mi_func {
  mi_cdigo }.

  Llamar a la funcin es como llamar a otro programa, slo hay que
  escribir su nombre.


  88..11..  EEjjeemmpplloo ddee ffuunncciioonneess



                  #!/bin/bash
                  function salir {
                      exit
                  }
                  function hola {
                      echo Hola!
                  }
                  hola
                  salir
                  echo petete



  Las lneas 2-4 contienen la funcin 'salir'. Las lneas 5-7 contienen
  la funcin 'hola'. Si no est completamente seguro de lo que hace este
  script, por favor, prubelo!.

  Tenga en cuenta que una funcin no necesita que sea declarada en un
  orden especfico.

  Cuando ejecute el script se dar cuenta de que: primero se llama a la
  funcin 'hola', luego a la funcin 'quit', y el programa nunca llega a
  la lnea 10.

  88..22..  EEjjeemmpplloo ddee ffuunncciioonneess ccoonn ppaarrmmeettrrooss



                       #!/bin/bash
                       function salir {
                          exit
                       }
                       function e {
                           echo $1
                       }
                       e Hola
                       e Mundo
                       salir
                       echo petete



  Este script es casi idntico al anterior. La diferencia principal es
  la funcin 'e'. Esta funcin imprime el primer argumento que recibe.
  Los argumentos, dentro de las funciones, son tratados de la misma
  manera que los argumentos suministrados al script.

  99..  IInntteerrffaacceess ddee uussuuaarriioo

  99..11..  UUttiilliizzaannddoo sseelleecctt ppaarraa hhaacceerr mmeennss sseenncciillllooss



                  #!/bin/bash
                  OPCIONES="Hola Salir"
                  select opt in $OPCIONES; do
                      if [ "$opt" = "Salir" ]; then
                       echo done
                       exit
                      elif [ "$opt" = "Hola" ]; then
                       echo Hola Mundo
                      else
                       clear
                       echo opcin errnea
                      fi
                  done



  Si ejecuta este script ver que es el sueo de un programador para
  hacer mens basados en texto. Probablemente se dar cuenta de que es
  muy similar a la construccin 'for', slo que en vez de iterar para
  cada 'palabra' en $OPCIONES, se lo pide al usuario.

  99..22..  UUttiilliizzaannddoo llaa llnneeaa ddee ccoommaannddooss



                 #!/bin/bash
                 if [ -z "$1" ]; then
                     echo uso: $0 directorio
                     exit
                 fi
                 SRCD=$1
                 TGTD="/var/backups/"
                 OF=home-$(date +%Y%m%d).tgz
                 tar -cZf $TGTD$OF $SRCD



  Lo que hace este script debera estar claro para usted. La expresin
  del primer condicional comprueba si el programa ha recibido algn
  argumento ($1) y sale si no lo ha recibido, mostrndole al usuario un
  pequeo mensaje de uso. El resto del script debera estar claro.

  1100..  MMiisscceellnneeaa

  1100..11..  LLeeyyeennddoo iinnffoorrmmaacciinn ddeell uussuuaarriioo

  En muchas ocasiones, puede querer solicitar al usuario alguna
  informacin, y existen varias maneras para hacer esto. sta es una de
  ellas:


                       #!/bin/bash
                       echo Por favor, introduzca su nombre
                       read NOMBRE
                       echo "Hola $NOMBRE!"



  Como variante, se pueden obtener mltiples valores con read. Este
  ejemplo debera clarificarlo.


                       #!/bin/bash
                       echo Por favor, introduzca su nombre y primer apellido
                       read NO AP
                       echo "Hola $AP, $NO!"



  1100..22..  EEvvaalluuaacciinn aarriittmmttiiccaa

  Pruebe esto en la lnea de comandos (o en una shell):

  echo 1 + 1

  Si esperaba ver '2', quedar desilusionado. Qu hacer si quiere que
  BASH evale unos nmeros? La solucin es sta:


  echo $((1+1))

  Esto producir una salida ms 'lgica'. Esto se hace para evaluar una
  expresin aritmtica. Tambin puede hacerlo de esta manera:

  echo $[1+1]


  Si necesita usar fracciones, u otras matemticas, puede utilizar bc
  para evaluar expresiones aritmticas.

  Si ejecuta "echo $[3/4]" en la lnea de comandos, devolver 0, porque
  bash slo utiliza enteros en sus respuestas. Si ejecuta "echo 3/4|bc
  -l", devolver 0.75.

  1100..33..  EEnnccoonnttrraannddoo eell bbaasshh

  De un mensaje de mike (vea los agradecimientos):

  siempre usas #!/bin/bash .. a lo mejor quieres dar un ejemplo

  de cmo saber dnde encontrar el bash.

  `locate bash' es preferible, pero no todas las mquinas

  tienen locate.

  `find ./ -name bash' desde el directorio raz funcionar,

  normalmente.

  Sitios donde poder buscar:

  ls -l /bin/bash

  ls -l /sbin/bash

  ls -l /usr/local/bin/bash

  ls -l /usr/bin/bash

  ls -l /usr/sbin/bash

  ls -l /usr/local/sbin/bash

  (no se me ocurre ningn otro directorio...  lo he encontrado

  la mayora de estos sitios en sistemas diferentes).

  Tambin puedes probar 'which bash'.

  1100..44..  OObbtteenniieennddoo eell vvaalloorr ddeevvuueellttoo ppoorr uunn pprrooggrraammaa

  En bash, el valor de retorno de un programa se guarda en una variable
  especial llamada $?.

  Esto ilustra cmo capturar el valor de retorno de un programa. Supongo
  que el directorio _d_a_d_a no existe. (Esto tambin es sugerencia de
  Mike).



          #!/bin/bash
          cd /dada &> /dev/null
          echo rv: $?
          cd $(pwd) &> /dev/null
          echo rv: $?



  1100..55..  CCaappuurraannddoo llaa ssaalliiddaa ddee uunn ccoommaannddoo

  Este pequeo script muestra todas las tablas de todas las bases de
  datos (suponiendo que tenga MySQL instalado).  Considere tambin
  cambiar el comando 'mysql' para que use un nombre de usuario y clave
  vlidos.


               #!/bin/bash
               DBS=`mysql -uroot  -e"show databases"`
               for b in $DBS ;
               do
                       mysql -uroot -e"show tables from $b"
               done



  1111..  TTaabbllaass

  1111..11..  OOppeerraaddoorreess ddee ccoommppaarraacciinn ddee ccaaddeennaass


     ss11 == ss22
        s1 coincide con s2


     ss11 !!== ss22
        s1 no coincide con s2


     ss11 << ss22
        s1 es alfabticamente anterior a s2, con el _l_o_c_a_l_e actual


     ss11 >> ss22
        s1 es alfabticamente posterior a s2, con el _l_o_c_a_l_e actual


     --nn ss11
        s1 no es nulo (contiene uno o ms caracteres)


     --zz ss11
        s1 es nulo

  1111..22..  EEjjeemmpplloo ddee ccoommppaarraacciinn ddee ccaaddeennaass

  Comparando dos cadenas



          #!/bin/bash
          S1='cadena'
          S2='Cadena'
          if [ $S1!=$S2 ];
          then
                  echo "S1('$S1') no es igual a S2('$S2')"
          fi
          if [ $S1=$S1 ];
          then
                  echo "S1('$S1') es igual a S1('$S1')"
          fi



  Cito aqu el consejo de un correo enviado por Andreas Beck, referido
  al uso de _i_f _[ _$_1 _= _$_2 _].

  Esto no es buena idea, porque si $S1 o $S2 son vacos, aparecer un
  _p_a_r_s_e _e_r_r_o_r. Es mejor: x$1=x$2 or "$1"="$2"


  1111..33..  OOppeerraaddoorreess aarriittmmttiiccooss

  + (adicin)

  - (sustraccin)

  * (producto)

  / (divisin)

  % (mdulo)

  1111..44..  OOppeerraaddoorreess rreellaacciioonnaalleess aarriittmmttiiccooss

  -lt (<)

  -gt (>)

  -le (<=)

  -ge (>=)

  -eq (==)

  -ne (!=)

  Los programadores de C tan slo tienen que corresponder el operador
  con su parntesis.

  1111..55..  CCoommaannddooss ttiilleess

  Esta seccin ha sido reescrita por Kees (vanse agradecimientos)

  Algunos de estos comandos contienen lenguajes de programacin
  completos. Slo se explicarn las bases de estos comandos. Para una
  descripcin ms detallada, eche un vistazo a las pginas man de cada
  uno.

  sseedd (editor de flujo)


  Sed es un editor no interactivo. En vez de alterar un fichero moviendo
  el cursor por la pantalla, se utiliza una serie de instrucciones de
  edicin de sed, y el nombre del fichero a editar. Tambin se puede
  describir a sed como un filtro. Miremos algunos ejemplos:



               $sed 's/a_sustituir/sustituto/g' /tmp/petete



  Sed sustituye la cadena 'a_sustituir' por la cadena 'sustituto',
  leyendo del fichero /tmp/petete. El resultado se enva a stdout
  (normalmente la consola), pero se puede aadir '> captura' al final de
  la lnea de arriba para que sed enve la salida al fichero 'capture'.



               $sed 12, 18d /tmp/petete



  Sed muestra todas las lneas de /tmp/petete excepto la 12 y la 18. El
  fichero original no queda alterado por este comando.

  aawwkk (manipulacin de bases de datos, extraccin y proceso de texto)


  Existen muchas implementaciones del lenguaje de programacin AWK (los
  intrpretes ms conocidos son gawk de GNU, y el 'nuevo awk' mawk).  El
  principio es sencillo: AWK busca un patrn, y por cada patrn de
  bsqueda que coincida, se realiza una accin.

  Si tenemos un fichero /tmp/petete con las siguientes lneas:

  _"_p_r_u_e_b_a_1_2_3

  _p_r_u_e_b_a

  _p_p_r_r_u_u_e_e_b_b_a_a_"


  y ejecutamos:


               $awk '/prueba/ {print}' /tmp/petete



  test123


  test


  El patrn que busca AWK es 'prueba' y la accin que realiza cuando
  encuentra una lnea en /tmp/petete con la cadena 'prueba' es `print'.


               $awk '/prueba/ {i=i+1} END {print i}' /tmp/petete



  3


  Cuando se utilizan muchos patrones, se puede reemplazar el texto entre
  comillas por '-f fichero.awk', y poner todos los patrones y acciones
  en 'fichero.awk'.

  ggrreepp (impresin de lneas que coinciden con un patrn de bsqueda)


  Ya hemos visto ejemplos del comando grep en los captulos anteriores,
  que muestra las lneas que concuerdan con un patrn. Pero grep puede
  hacer ms que eso.


               $grep "busca esto" /var/log/messages -c



  12

  Se ha encontrado 12 veces la cadena "busca esto" en el fichero
  /var/log/messages.


  [vale, este ejemplo es falso, el fichero /var/log/messages est
  alterado :-)]

  wwcc (cuenta lneas, palabras y bytes)


  En el siguiente ejemplo, vemos que la salida no es lo que esperbamos.
  El fichero petete utilizado en este ejemplo contiene el texto
  siguiente:

  _"_p_r_o_g_r_a_m_a_c_i__n _e_n _b_a_s_h
  _c_o_m_o _d_e _i_n_t_r_o_d_u_c_c_i__n_"



               $wc --words --lines --bytes /tmp/petete



  2 5 41 /tmp/petete


  Wc no tiene en cuenta el orden de los parmetros. Wc siempre los
  imprime en un orden estndar, que es, como se puede ver: lneas,
  palabras, bytes y fichero.

  ssoorrtt (ordena lneas de ficheros de texto)


  Esta vez, el fichero petete contiene el texto siguiente:

  _"_b
  _c
  _a_"


               $sort /tmp/petete



  Esto es lo que muestra la salida:


  _a
  _b
  _c


  Los comandos no deberan ser tan fciles :-)

  bbcc (un lenguaje de programacin de clculos matemticos)


  Bc acepta clculos desde la lnea de comandos (entrada desde un
  fichero, pero no desde una redireccin o una tubera), y tambin desde
  una interfaz de usuario. La siguiente demostracin expone algunos de
  los comandos. Note que  ejecuto bc con el parmetro -q para evitar el
  mensaje de bienvenida.



          $bc -q



  _1 _=_= _5

  _0

  _0_._0_5 _=_= _0_._0_5

  _1

  _5 _!_= _5

  _0

  _2 _^ _8

  _2_5_6

  _s_q_r_t_(_9_)

  _3

  _w_h_i_l_e _(_i _!_= _9_) _{

  _i _= _i _+ _1_;

  _p_r_i_n_t _i

  _}

  _1_2_3_4_5_6_7_8_9

  _q_u_i_t

  ttppuutt (inicializa una terminal o consulta la base de datos de terminfo)


  Una pequea demostracin de las capacidades de tput:


               $tput cup 10 4



  La lnea de comandos aparece en (y10,x4).


               $tput reset



  Limpia la pantalla y la lnea de comandos aparece en (y1,x1).  Observe
  que (y0,x0) es la esquina superior izquierda.


               $tput cols



  _8_0

  Muestra el nmero de caracteres que caben en la direccin x.

  Es muy recomendable familiarizarse con estos programas (al menos).
  Hay montones de programillas que le permitirn hacer virgueras en la
  lnea de comandos.

  [algunos ejemplos estn copiados de las pginas man o los PUFs]

  1122..  MMss ssccrriippttss

  1122..11..  AApplliiccaannddoo uunn ccoommaannddoo aa ttooddooss llooss ffiicchheerrooss ddee uunn ddiirreeccttoorriioo..



  1122..22..  EEjjeemmpplloo:: UUnn ssccrriipptt ddee ccooppiiaa ddee sseegguurriiddaadd mmuuyy ssiimmppllee ((aallggoo
  mmeejjoorr))



              #!/bin/bash
              ORIG="/home/"
              DEST="/var/copias_de_seguridad/"
              FICH=home-$(date +%Y%m%d).tgz
              tar -cZf $DEST$FICH $ORIG



  1122..33..  RRee--nnoommbbrraaddoorr ddee ffiicchheerrooss



               #!/bin/sh
               # renom: renombra mltiples ficheros de acuerdo con ciertas
               # reglas
               # escrito por Felix Hudson  Enero - 2000

               # primero comprueba los distintos 'modos' que tiene este
               # programa
               # si la primera ($1) condicin coincide, se ejecuta esa parte
               # del programa y acaba

               # comprueba la condicin de prefijo
               if [ $1 = p ]; then

               # ahora nos libramos de la variable de modo ($1) y ponemos $2
               # de prefijo
                 prefijo=$2 ; shift ; shift

               # una rpida comprobacin para ver si se especific algn
               # fichero
               # si no, hay cosas mejores que hacer que renombrar ficheros
               # inexistentes!!
                 if [$1 = ]; then
                    echo "no se especificaron ficheros"
                    exit 0
                 fi

               # este bucle for itera a lo largo de todos los ficheros que
               # le hemos especificado al programa
               # renombra cada uno de ellos
                 for fichero in $*
                   do
                   mv ${fichero} $prefijo$fichero
                 done

               # ahora salimos del programa
                 exit 0
               fi

               # comprueba si es un renombramiento con sufijo
               # el resto es casi idntico a la parte anterior
               # lea los comentarios anteriores
               if [ $1 = s ]; then
                 sufijo=$2 ; shift ; shift

                  if [$1 = ]; then
                   echo "no se especificaron ficheros"
                  exit 0
                  fi

                for fichero in $*
                 do
                  mv ${fichero} $fichero$sufijo
                done

                exit 0
               fi

               # comprueba si es una sustitucin
               if [ $1 = r ]; then

                 shift

               # he includo esto para no daar ningn fichero si el
               # usuario no especifica que se haga nada
               # tan slo una medida de seguridad
                 if [ $# -lt 3 ] ; then
                   echo "uso: renom r [expresin] [sustituto] ficheros... "
                   exit 0
                 fi

               # elimina el resto de informacin
                 VIEJO=$1 ; NUEVO=$2 ; shift ; shift

               # este bucle for itera a lo largo de todos los ficheros que
               # le hemos especificado al programa
               # renombra cada fichero utilizando el programa 'sed'
               # es un sencillo programa desde la lnea de comandos que
               # analiza la entrada estndar y sustituye una expresin por
               # una cadena dada
               # aqu le pasamos el nombre del fichero (como entrada
               # estndar)
                 for fichero in $*
                 do
                   nuevo=`echo ${fichero} | sed s/${VIEJO}/${NUEVO}/g`
                   mv ${fichero} $nuevo
                 done
               exit 0
               fi

               # si se llega a esta parte es que no se le pas nada
               # apropiado al programa, por lo que le decimos al usuario
               # cmo hacerlo
               echo "uso:"
               echo " renom p [prefijo] ficheros.."
               echo " renom s [sufijo] ficheros.."
               echo " renom r [expresin] [sustituto] ficheros.."
               exit 0

               # hecho!



  1122..44..  RRee--nnoommbbrraaddoorr ddee ffiicchheerrooss ((sseenncciilllloo))



            #!/bin/bash
            # renombra.sh
            # renombrador de ficheros bsico

            criterio=$1
            expresion=$2
            sustituto=$3

            for i in $( ls *$criterio* );
            do
                orig=$i
                dest=$(echo $i | sed -e "s/$expresion/$sustituto/")
                mv $orig $dest
            done



  1133..  CCuuaannddoo aallggoo vvaa mmaall ((ddeeppuurraacciinn))



  1133..11..  MMaanneerraass ddee llllaammaarr aa BBAASSHH

  Una buena idea es poner esto en la primera lnea:


                 #!/bin/bash -x



  Esto producir informacin interesante.

  1144..  SSoobbrree eell ddooccuummeennttoo

  Sintase libre para hacer sugerencias/correcciones, o lo que crea que
  sea interesante que aparezca en este documento. Intentar actualizarlo
  tan pronto como me sea posible.

  1144..11..  ((ssiinn)) GGaarraannttaa

  Este documento no lleva garanta de ningn tipo.

  1144..22..  TTrraadduucccciioonneess

  Italiano: por William Ghelfi (wizzy est en tiscalinet.it).
  http://web.tiscalinet.it/penguin_rules

  Francs: por Laurent Martelli ?

  Coreano: Minseok Park http://kldp.org

  Corean: Chun Hye Jin Desconocido

  Spanish: Gabriel Rodrguez Alberich http://www.insflug.org

  Supongo que habr ms traducciones, pero no tengo informacin sobre
  ellas. Si las tiene, por favor, envemelas para que actualice esta
  seccin.


  1144..33..  AAggrraaddeecciimmiieennttooss


    A la gente que ha traducido este documento a otras lenguas (seccin
     anterior).

    A Nathan Hurst por enviar montones de correcciones.

    A Jon Abbott por enviar comentarios sobre la evaluacin de
     expresiones aritmticas.

    A Felix Hudson por escribir el script _r_e_n_o_m

    A Kees van den Broek (por enviar tantas correcciones y reescribir
     la seccin de comandos tiles)

    Mike (pink) hizo algunas sugerencias sobre la localizacin del bash
     y la comprobacin de los ficheros

    Fiesh hizo una buena sugerencia sobre la seccin de bucles.

    Lion sugiri mencionar un error comn (./hello.sh: Comando no
     encontrado.)


    Andreas Beck hizo varias correcciones y comentarios.

  1144..44..  HHiissttoorriiaa

  Aadidas nuevas traducciones y correcciones menores.

  Aadida la seccin de comandos tiles reescrita por Kess.

  Incorporadas ms correcciones y sugerencias.

  Aadidos ejemplos sobre la comparacin de cadenas.

  v0.8 abandono del versionamiento. Supongo que con la fecha es
  suficiente.

  v0.7 Ms correcciones y algunas secciones TO-DO escritas.

  v0.6 Correcciones menores.

  v0.5 Aadida la seccin de redireccionamiento.

  v0.4 desaparicin de su sitio debido a mi ex-jefe. Este documento
  tiene un nuevo sitio en: http://www.linuxdoc.org.

  Anteriores: no me acuerdo y no he usado rcs ni cvs :(

  1144..55..  MMss rreeccuurrssooss


  Introduccin a bash (bajo BE)
  http://org.laol.net/lamug/beforever/bashtut.htm

  Programacin en Bourne Shell http://207.213.123.70/book/



