166
El shell Bash

Manual Completo Bash Script

Embed Size (px)

DESCRIPTION

Programación de Bash

Citation preview

  • El shell Bash

  • El shell Bash macprogramadores.org

    Pg 2

    Acerca de este documento

    En este tutorial pretendemos ensear el manejo de Bash, el Bourne AgainShell de GNU. Este shell es el que proporcionan por defecto muchos sistemasUNIX entre ellos Mac OS X o Linux. Los ejemplos se explicarn sobre Mac OSX, pero debido a la interoperatividad que caracteriza a Bash, estos ejemplosdeberan ser exactamente igual de tiles en otros sistemas UNIX. Cuandoexistan diferencias las indicaremos para que usuarios de otros sistemaspuedan seguir correctamente este documento.

    El tutorial asume que el lector conoce los aspectos ms bsicos de qu es, ypara qu sirve un terminal. No pretendemos ensear cuales son los muchos ytiles comandos a los que podemos acceder, slo pretendemos centrarnos enel manejo, personalizacin y programacin de scripts con el shell Bash. Aunas, a lo largo del documento comentaremos gran cantidad de comandos queestn relacionados con el shell, y que ayudan a hacer que los ejemplosresulten tiles.

    Al acabar este tutorial el lector debera de haber aprendido a usar lasprincipales teclas rpidas, personalizar mucho ms su terminal para hacerloms manejable, y modificar o crear los scripts que configuran su sistema.

    Nota legal

    Este tutorial ha sido escrito por Fernando Lpez Hernndez paramacprogramadores.org y de acuerdo a las leyes internacionales sobrepropiedad intelectual, a la Directiva 2001/29/CE del Parlamento Europeo de22 de mayo de 2001 y al artculo 5 de la Ley 22/1987 de 11 de Noviembre dePropiedad Intelectual Espaola, el autor prohbe la publicacin de estedocumento en cualquier otro servidor web, as como su venta, o difusin encualquier otro medio sin autorizacin previa.

    Sin embargo el autor anima a todos los servidores web a colocar enlaces aeste documento. El autor tambin anima a cualquier persona interesada enconocer el shell Bash, y que ventajas que aporta tanto al usuario como alprogramador, a bajarse o imprimirse este tutorial.

    Madrid, Septiembre 2005Para cualquier aclaracin contacte con:[email protected]

  • El shell Bash macprogramadores.org

    Pg 3

    Tabla de contenido

    TEMA 1: Introduccin a Bash

    1. El shell que estamos usando ................................................................82. Expansin de nombres de ficheros y directorios .................................. 10

    2.1. Los comodines............................................................................ 102.2. El comodn tilde.......................................................................... 112.3. El comodn llaves ........................................................................ 122.4. Comodines extendidos ................................................................ 13

    3. Los comandos internos de Bash ......................................................... 154. Redirecciones y pipes ........................................................................ 16

    4.1. Operadores de redireccin........................................................... 164.2. Pipes.......................................................................................... 17

    5. Ejecucin secuencial y concurrente de comandos ................................ 196. Caracteres especiales y entrecomillado ............................................... 20

    6.1. Entrecomillado............................................................................ 206.2. Caracteres de escape.................................................................. 216.3. Entrecomillar los entrecomillados ................................................. 226.4. Texto de varias lneas ................................................................. 22

    TEMA 2: Combinaciones de teclas

    1. El historial de comandos .................................................................... 251.1. El comando fc ........................................................................... 251.2. Ejecutar comandos anteriores...................................................... 26

    2. Las teclas de control del terminal ....................................................... 273. Modos de edicin en la lnea de comandos.......................................... 29

    3.1. Moverse por la lnea.................................................................... 293.2. Borrar partes de la lnea.............................................................. 303.3. Buscar en el historial................................................................... 303.4. Autocompletar con el tabulador ................................................... 31

    4. La librera readline............................................................................. 324.1. El fichero de configuracin .......................................................... 324.2. Asignacin de teclas de sesin..................................................... 34

  • El shell Bash macprogramadores.org

    Pg 4

    TEMA 3: Personalizar el entorno

    1. Los ficheros de configuracin de Bash ................................................ 372. Los alias ........................................................................................... 383. Las opciones de Bash ........................................................................ 394. Las variables de entorno.................................................................... 41

    4.1. Variables y entrecomillado........................................................... 414.2. Personalizar el prompt ................................................................ 414.3. Variables de entorno internas ...................................................... 444.4. Exportar variables....................................................................... 44

    TEMA 4: Programacin bsica del shell

    1. Scripts y funciones ............................................................................ 461.1. Scripts ....................................................................................... 461.2. Funciones................................................................................... 461.3. Orden de preferencia de los smbolos de Bash.............................. 47

    2. Variables del shell.............................................................................. 492.1. Los parmetros posicinales........................................................ 492.2. Variables locales y globales ......................................................... 502.3. Las variables $*, $@ y $#............................................................ 522.4. Expansin de variables usando corchetes ..................................... 55

    3. Operadores de cadena....................................................................... 563.1. Operadores de sustitucin........................................................... 563.2. Operadores de bsqueda de patrones.......................................... 593.3. El operador longitud ................................................................... 62

    4. Sustitucin de comandos ................................................................... 63

    TEMA 5: Control de flujo

    1. Las sentencias condicionales .............................................................. 691.1. Las sentencias if, elif y else ................................................. 691.2. Los cdigos de terminacin ......................................................... 691.3. Las sentencias return y exit ................................................... 701.4. Operadores lgicos y cdigos de terminacin ............................... 721.5. Test condicionales ...................................................................... 73

    2. El bucle for ..................................................................................... 793. Los bucles while y until ................................................................ 824. La sentencia case............................................................................. 835. La sentencia select......................................................................... 85

  • El shell Bash macprogramadores.org

    Pg 5

    TEMA 6: Opciones de lnea de comandos, expresiones aritmticas y arrays

    1. Opciones de la lnea de comandos...................................................... 881.1. La sentencia shift .................................................................... 881.2. El comando interno getopts...................................................... 90

    2. Variables con tipo.............................................................................. 933. Expresiones aritmticas ..................................................................... 96

    3.1. Similitud con las expresiones aritmticas C ................................... 963.2. El comando interno let.............................................................. 973.3. Sentencias de control de flujo aritmticas..................................... 993.4. Arrays ...................................................................................... 101

    TEMA 7: Redicecciones

    1. Redirecciones.................................................................................. 1081.1. Los descriptores de fichero........................................................ 1091.2. El comando exec ..................................................................... 1111.3. Here documents ....................................................................... 112

    2. Entrada y salida de texto ................................................................. 1152.1. El comando interno echo.......................................................... 1152.2. El comando interno printf...................................................... 1162.3. El comando interno read.......................................................... 119

    3. Los bloques de comandos ................................................................ 1224. Los comandos comand, builtin y enable .................................... 1255. El comando interno eval ................................................................ 126

  • El shell Bash macprogramadores.org

    Pg 6

    TEMA 8: Control de procesos

    1. IDs de procesos y nmeros de jobs .................................................. 1302. Control de jobs................................................................................ 131

    2.1. Foreground y background ......................................................... 1312.2. Suspender y reanudar un job .................................................... 1322.3. El comando ps ......................................................................... 1332.4. El comando top ....................................................................... 135

    3. Seales........................................................................................... 1363.1. Combinaciones de teclas que envan seales .............................. 1373.2. El comando interno kill.......................................................... 137

    4. Capturar seales desde un script...................................................... 1394.1. El comando interno trap.......................................................... 1394.2. Traps y funciones ..................................................................... 1404.3. IDs de proceso ......................................................................... 1414.4. Ignorar seales ........................................................................ 142

    5. Corutinas ........................................................................................ 1446. Subshells ........................................................................................ 1467. La sustitucin de procesos ............................................................... 147

    TEMA 9: Depurar scripts

    1. Opciones de Bash para depuracin................................................... 1492. Fake signals .................................................................................... 152

    2.1. La seal SIGEXIT .................................................................... 1522.2. La seal SIGERR ...................................................................... 1532.3. La seal SIGDEBUG .................................................................. 1542.4. La seal SIGRETURN ................................................................ 154

    3. Un depurador Bash.......................................................................... 1553.1. Estructura del depurador........................................................... 1553.2. El driver ................................................................................... 1553.3. El prembulo ............................................................................ 1573.4. Funciones del depurador ........................................................... 1583.5. Ejemplo de ejecucin ................................................................ 165

    Referencias

  • El shell Bash macprogramadores.org

    Pg 7

    Tema 1

    Introduccin aBash

    Sinopsis:

    Como se justifica en el acerca de, este tutorial va a omitir los aspectos msbsicos del shell que es normal conocer por parte de cualquier persona quehaya usado mnimamente un shell UNIX.

    En este primer tema vamos a repasar un conjunto de temas bsicos que,aunque en parte puede conocer el lector, creemos que conviene aclarar antesde profundizar.

    Por consiguiente, recomendamos empezar leyendo este primer tema, ya quesino pueden quedar ciertos aspectos sin concretar que luego podran hacerfalta para seguir ms cmodamente las explicaciones.

    Debido a sus objetivos, este tema est escrito avanzando de formaconsiderablemente ms rpida y superficial que en resto de temas.

  • El shell Bash macprogramadores.org

    Pg 8

    1. El shell que estamos usando

    Mac OS X trae preinstalado el shell Bash desde la versin 10.2, antes traainstalado el shell tcsh, pero debido a que Bash es el shell que GNU eligi parael software libre, Apple decidi dar el salto. Linux lgicamente tambin usaeste shell, con lo cual parece ser que Bash es el shell de los sistemas UNIXms utilizados, y tiene un futuro muy prometedor.

    Si queremos saber que versin de shell tenemos instalado podemos usar elcomando:

    $ echo $SHELL/bin/bash

    Este comando nos indica que shell estamos usando y en que directorio estinstalado.

    Si queremos conocer la versin de Bash podemos usar el comando:

    $ echo $BASH_VERSION2.05b.0(1)-release

    Tambin podemos saber donde est instalado Bash con el comando:

    $ whereis bash/bin/bash

    Puede conocer todos los shell de que dispone su mquina con el comando:

    $ cat /etc/shells/bin/bash/bin/csh/bin/sh/bin/tcsh/bin/zsh

    Si por alguna razn no est usando Bash, pero lo tiene instalado (o lo acabade instalar) en su mquina, puede hacer que Bash sea el shell por defecto desu cuenta usando el comando:

    $ chsh -s /bin/bash

    Si prefiere usar una versin ms moderna de shell que la que vienepreinstalada con Mac OS X puede bajrsela del proyecto Fink:

  • El shell Bash macprogramadores.org

    Pg 9

    $ fink list bashInformation about 4975 packages read in 12 seconds. bash 3.0-2 The GNU Bourne Again Shell bash-completion 20041017-1 Command-line completions ... bash-doc 3.0-1 Extra documentation for ...

    $ fink install bash

    Y cambiar a este shell con:

    $ chsh -s /sw/bin/bash

    Pero antes deber introducir este shell en /etc/shells, o chsh no se loaceptar como un shell vlido.

    Si ahora nos logamos de nuevo con el comando login y preguntamos por laversin de Bash:

    $ echo $BASH/sw/bin/bash$ echo $BASH_VERSION3.00.0(1)-release

    Vemos que estamos trabajando con Bash 3.0. En este tutorial supondremosque tenemos la versin 3.0 de Bash, si alguien est usando la versin 2.05, oalguna anterior, puede que no le funcionen todos los ejemplos que hagamos.

  • El shell Bash macprogramadores.org

    Pg 10

    2. Expansin de nombres de ficheros ydirectorios

    2.1. Los comodinesPara referirnos a varios ficheros es muy tpico usar los comodines de la Tabla1.1. Un sitio tpico donde se usan los comodines es el comando ls. Estecomando sin argumentos lista todos los ficheros del directorio, pero lepodemos pasar como argumentos los nombres de los ficheros que queremoslistar:

    $ ls carta.txt leeme.txt

    Si lo que le damos son los nombres de uno o ms directorios lo que hace eslistar su contenido.

    Comodn Descripcin? Uno y slo un carcter* Cero o ms caracteres[conjunto] Uno los caracteres de conjunto[!conjunto] Un carcter que no este en conjunto

    Tabla 1.1: Comodines de fichero

    Muchas veces queremos referirnos a un conjunto de ficheros para lo cualusamos comandos de la forma:

    $ ls *.txt

    Que lista todos los ficheros acabados en .txt.

    * representa cero o ms caracteres, con lo que *ed encontrara el fichero ed.

    Otro comodn menos usado es ? que sustituye por un slo carcter, porejemplo:

    $ ls carta?.txt

    Listara ficheros como carta1.txt, carta2.txt, pero no carta10.txt.

    El tercer comodn permite indicar un conjunto de caracteres que son vlidospara hacer la sustitucin, p.e. c[ao]sa encontrara el fichero casa y cosa,pero no cesa. Adems podemos indicar un conjunto de caracteres ASCIIconsecutivos, por ejemplo [a-z] seran todas las letras minsculas, [!0-9]

  • El shell Bash macprogramadores.org

    Pg 11

    seran todos los caracteres ASCII excepto los dgitos, y [a-zA-Z0-9] serantodas las letras maysculas, minsculas y los dgitos.

    La razn por la que este comodn no ha sido tan usado como se esperaba esque expande por un, y slo un dgito, por ejemplo programa.[co]encontrara programa.c y programa.o, pero no programa.cpp.

    Es importante tener en cuenta que los comandos cuando se ejecutan no venlos comodines sino el resultado de la expansin. Por ejemplo si ejecutamos elcomando:

    $ cp g* /tmp

    g* se expande por todos los ficheros que cumplen el patrn, y esto es lo quese pasa al comando cp, pero si no existiera ningn fichero cuyo nombrecumpliese el patrn g*, este valor no se expande sino que se pasa tal cual alcomando, y ste ser el que fallar:

    $ cp g* /tmp/cp: g*: No such file or directory

    Es decir, como podramos pensar, al fallar no se pasa una lista vaca alcomando. Piense por un momento lo que ocurrira con algunos comandos sise hubiese diseado as.

    Este funcionamiento es ligeramente distinto al de tcsh, donde si no seexpande el comodn no se ejecuta el comando, en Bash se ejecuta elcomando aunque luego ste produzca un error.

    2.2. El comodn tildeEl comodn tilde ~ se usa para referirse al directorio home de los usuarios(/Users en Mac OS X o /home en la mayora de las mquinas UNIX), porejemplo si usamos ~carol/carta.txt nos lo expande por/Users/carol/carta.txt.

    Adems podemos usar el comodn tilde para referirnos a nuestro propiodirectorio, el cuyo caso debemos de precederlo por una barra, p.e.~/carta.txt se expande por el nombre de mi directorio, en mi caso/Users/fernando/carta.txt.

    Observe la diferencia entre poner la barra y no ponerla, si no la hubierapuesto (hubiera puesto ~carta.txt), me habra expandido por la ruta/Users/carta.txt, y si no existe un usuario con el nombre carta.txthubiera producido un error indicando que no existe el directorio.

  • El shell Bash macprogramadores.org

    Pg 12

    2.3. El comodn llavesEl comodn llaves, a diferencia de los anteriores, no estudia el nombre de losficheros existentes en disco para nada, simplemente expande una palabra porcada una de las cadenas de caracteres que contiene, por ejemplo:

    $ echo c{ami,ontamina,}oncamion contaminaon con

    Es posible incluso anidarlo y genera el producto cartesiano de combinaciones:

    $ echo c{a{min,nt}a,ose}rcaminar cantar coser

    En el apartado 2.1 comentamos que un problema que tena el comodncorchete es que expanda por un y slo un carcter, lo cual era problemticosi queramos referirnos por ejemplo a todos los ficheros de un programa, yaque *.[coh] nos permite referirnos a los fichero .c, .o y .h, pero no a los.cpp.

    Usando el comodn llave podemos superar esta dificultad: *.{h,c,cpp,o}espadera en todos los ficheros con estas extensiones, aunque ahora surge unnuevo problema y es que, debido a que el comodn llave no mira que ficheroshay en disco, si no existe un fichero con alguna de las extensiones indicadas,la expansin del * no se produce, y encontraramos un mensaje de error. Porejemplo:

    $ ls *.{h,c,cpp,o}ls: *.c: No such file or directoryls: *.o: No such file or directoryclave.cpp clave.h

    Se puede usar .. para hacer algo similar a lo que hacen los corchetesobteniendo todos lo caracteres ASCII entre dos letras. Por ejemplo:

    $ echo l{a..e}la lb lc ld le

    Obsrvese que, en el caso de los corchetes, lo que obtendramos no son unconjunto de cinco palabras, sino una expansin por un fichero existente:

    $ echo cl[a-e]ve.hclave.h

    O la cadena sin expandir si no se encuentra el fichero:

    $ echo cl[e-i]ve.h

  • El shell Bash macprogramadores.org

    Pg 13

    cl[e-i]ve.h

    Por ltimo comentar que la llave debe contener al menos dos cadenas, sinono se realiza la expansin:

    $ echo ca{a}saca{a}sa

    De nuevo este comportamiento difiere con el de tcsh, donde la expansin serealiza aunque haya una sola cadena dentro de las llaves.

    2.4. Comodines extendidosBash permite usar un conjunto de comodines extendidos, pero para poderusarlos debemos de activar la opcin ext_glob de Bash (vase el apartado3 del Tema 3) con el comando:

    $ shopt -s extglob

    En este caso se pueden usar uno de estos cinco nuevos tipos de patrones:

    ?(pattern-list)Cero o una ocurrencia de pattern-list

    *(pattern-list)Cero o ms ocurrencias de pattern-list

    +(pattern-list)Una o ms ocurrencias de pattern-list

    @(pattern-list)Exactamente uno de los patrones de la lista

    !(pattern-list)Cualquier cosa excepto uno de los patrones de la lista

    pattern-list recibe uno o ms patrones separados por |. Cada patrn deesta lista puede contener comodines, por ejemplo +([0-9]) busca cadenasformadas por uno o ms dgitos.

    En el apartado 2.1 vimos que un problema que presentaba el comodn ? eraque carta?.txt listara ficheros como carta1.txt, carta2.txt, pero nocarta10.txt. Esto lo podemos solucionar con el comodn extendido+(pattern-list) de la forma: carta+([0..9]).txt

  • El shell Bash macprogramadores.org

    Pg 14

    Tambin vimos en el apartado 2.1 que *.[cho] encontrara los ficheros conextensin .c, .o y .h, pero no haba forma de encontrar los .cpp ya que elcorchete slo aceptaba un carcter. Ahora podemos usar el comodn@(pattern-list) para indicar la lista de extensiones a aceptar. Porejemplo *.@(c|o|h|cpp) encontrara correctamente estos ficheros:

    $ ls *.@(c|o|h|cpp)clave.cpp clave.h

    Tambin hubiera sido equivalente usar @(*.c|*.o|*.h|*.cpp) ya que lospatrones pueden estar anidados.

    Si lo que hubiramos querido es encontrar todos los ficheros excepto los.gif , los .jpg y los .html podramos haber usado el patrn!(*.html|*gif|*jpg). Sin embargo, en este caso no podramos haberusado *.!(html|gif|jpg)

    Un ltimo ejemplo, si queremos borrar todos los ficheros excepto los queempiezan por vt seguido por uno o ms dgitos podemos usar el comando:

    $ rm !(vt+([0-9]))

  • El shell Bash macprogramadores.org

    Pg 15

    3. Los comandos internos de Bash

    Bash busca los comandos a ejecutar en los directorios indicados en la variablede entorno $PATH, pero adems existen una serie de comandos que nocorresponden a ficheros del disco duro, sino que son internos a Bash y estnsiempre cargados en su memoria.

    Ejemplos de estos comandos son cd, chdir, alias, set o export. Puedeobtener una lista completa de estos comandos con su descripcin ejecutando:

    $ man builtin

    Y puede obtener ayuda de estos comandos usando el comando help:

    $ help aliasalias: alias [-p] [name[=value] ... ]`alias' with no arguments or with the -p option printsthe list of aliases in the form alias NAME=VALUE onstandard output.Otherwise, an alias is defined for each NAME whose VALUEis given.A trailing space in VALUE causes the next word to bechecked for alias substitution when the alias isexpanded. Alias returns true unless a NAME is given forwhich no alias has been defined.

  • El shell Bash macprogramadores.org

    Pg 16

    4. Redirecciones y pipes

    4.1. Operadores de redireccinUNIX est basado en una idea muy simple pero muy til: Tratar todos lasentrada y salidas como streams (flujos) de bytes.

    Cada programa va a tener asociadas siempre una entrada estndar (pordefecto el teclado), una salida estndar (por defecto la consola), y una salidade errores estndar (por defecto tambin la consola).

    Si queremos, podemos cambiar la entrada estndar para que el programareciba datos de un fichero usando el operador de redireccin

  • El shell Bash macprogramadores.org

    Pg 17

    $ date > ahora

    Enva el da y hora actuales al fichero ahora.

    Tambin podemos cambiar a la vez la entrada y salida estndar de unprograma usando ambos operadores de redireccin. Por ejemplo:

    $ cat < ficheroa > ficherob

    Tambin podemos cambiar la salida de errores estndar con el operador deredireccin 2>. Por ejemplo:

    $ cat < ficheroa > ficherob 2>errores

    Copia el ficheroa en el ficherob, y si se produce algn error lo escribe enel fichero errores.

    Si no queremos sobrescribir un fichero de salida sino aadir el contenido alfinal podemos usar el operador de redireccin >> para la salida estndar o2>> para los errores estndar. Por ejemplo:

    $ ls p* >>ficheros 2>>errores

    Aadira los ficheros que lista ls al fichero ficheros, y si se produjesenerrores los aadira al fichero errores. El operador de redireccin 2>> esespecialmente til para almacenar los conocidos logs de errores.

    Muchas veces no se quiere que un programa muestre mensajes en la consoladel usuario, en este caso es muy comn redirigir su salida estndar y salidade errores estndar al fichero /dev/null:

    $ gcc *.cpp > /dev/null 2> /dev/null

    4.2. PipesEs posible redirigir la salida estndar de un programa a la entrada estndarde otro usando el operador | (pipeline).

    more es uno de los comandos tpicos que lo usan. Este comando lo que hacees recoger la entrada estndar y irla mostrando poco a poco (pgina apgina), luego si por ejemplo tenemos un directorio con muchos ficherospodemos hacer:

    $ ls -la | more

    y se irn mostrando pgina a pgina los ficheros.

  • El shell Bash macprogramadores.org

    Pg 18

    Segn vayamos avanzando podremos ir viendo ejemplos ms complejos, porejemplo:

    $ cut -d: -f1 < /etc/passwd | sort

    Nos muestra los nombres de todos los usuarios de la mquina ordenadosalfabticamente.

    Tngase en cuenta que el operador | separa el comando en varios comandosantes de ejecutarlo, con lo que el operador de redireccin tiene efecto slopara el comando cut.

  • El shell Bash macprogramadores.org

    Pg 19

    5. Ejecucin secuencial y concurrente decomandos

    Podemos ejecutar un comando que tarde mucho en ejecutarse y dejarloejecutando en background precedindolo por &. Por ejemplo para compilar unconjunto de ficheros fuente de un programa C++ podemos hacer:

    $ gcc *.cpp &

    Aunque el proceso se sigue ejecutando en background, los mensajes queproduce salen en la consola impidindonos trabajan cmodamente. Paraevitarlo podemos enviar los mensajes a /dev/null:

    $ gcc *.cpp > /dev/null &

    Aunque si se produce un error, ste ir a la salida de errores estndar, con loque seguira saliendo en consola. Podramos evitarlo redirigiendo tambin lasalida de errores estndar, pero quiz sea mejor que se nos informase delerror.

    Otras veces lo que queremos es esperar a que se acabe de ejecutar uncomando para ejecutar el siguiente, en este caso podemos usar el operador ;(punto y coma), por ejemplo, podramos querer compilar el comando clavepara luego ejecutarlo:

    $ gcc clave.cpp -o clave ; clave

    Este comando primero compila el programa, y cuando acaba de compilarlo loejecuta.

  • El shell Bash macprogramadores.org

    Pg 20

    6. Caracteres especiales y entrecomillado

    Los caracteres , |, & * , ? , ~ , [ , ] , {, } son ejemplos de caracteresespeciales para Bash que ya hemos visto. La Tabla 1.2 muestra todos loscaracteres especiales de Bash.

    Ms adelante veremos otros comandos tienen sus propios caracteresespeciales, como puedan ser los comandos que usan expresiones regulares olos operadores de manejo de cadenas.

    Carcter Descripcin~ Directorio home` Sustitucin de comando# Comentario$ Variable& Proceso en background; Separador de comandos* Comodn 0 a n caracteres? Comodn de un slo carcter/ Separador de directorios( Empezar un subshell) Terminar un subshell\ Carcter de escape< Redirigir la entrada> Redirigir la salida| Pipe[ Empieza conjunto de caracteres comodn] Acaba conjunto de caracteres comodn{ Empieza un bloque de comando} Acaba un bloque de comando' Entrecomillado fuerte" Entrecomillado dbil! No lgico de cdigo de terminacin

    Tabla 1.2: Caracteres especiales de Bash

    6.1. EntrecomilladoAunque los caracteres especiales son muy tiles para Bash, a veces queremosusar un carcter especial literalmente, es decir sin su significado especial, eneste caso necesitamos entrecomillarlo (quoting).

    Por ejemplo si queremos escribir en consola el mensaje: 2*3>5 es unaexpresin cierta, podemos usar el comando echo as:

  • El shell Bash macprogramadores.org

    Pg 21

    $ echo 2*3>5 es una expresion cierta

    Al ejecutarlo podemos observar que no da ninguna salida, pero realmente hacreado el fichero 5 con el texto 2*3 es una expresion cierta. La raznest en que >5 ha sido entendido como redirigir al fichero 5, y adems se haintentado ejecutar el carcter especial *, pero al no encontrar ningn ficheroque cumpliera el patrn no se ha expandido y se ha pasado el parmetro aecho tal cual.

    Sin embargo si entrecomillamos usando ', el carcter de entrecomilladofuerte obtenemos el resultado esperado:

    $ echo '2*3>5 es una expresion cierta'2*3>5 es una expresion cierta

    Un ejemplo ms prctico del entrecomillado es el comando find que nospermite buscar ficheros por muchos criterios. Por ejemplo para buscar pornombre usa el argumento -name patron. Si por ejemplo queremos buscartodos los ficheros .c en nuestra mquina podemos intentar hacer:

    $ find / -name *.c

    Pero si tenemos la mala suerte de que en el directorio actual exista algnfichero .c, sustituir el comodn y buscar el nombre de el/los ficheros denuestro directorio actual en el disco duro. Para evitarlo es recomendableentrecomillarlo:

    $ find / -name '*.c'

    En la Tabla 1.2 aparece el entrecomillado dbil ", el cual pasa slo poralgunos de los pasos del shell, o dicho con otras palabras, interpreta sloalgunos caracteres especiales. Ms adelante veremos cuando es preferibleusar este tipo de entrecomillado, de momento usaremos slo elentrecomillado fuerte.

    6.2. Caracteres de escapeOtra forma de cambiar el significado de un carcter de escape es precederlopor \, que es lo que se llama el carcter de escape.

    Por ejemplo en el ejemplo anterior podramos haber hecho:

    $ echo 2\*3\>5 es una expresion cierta2*3>5 es una expresion cierta

  • El shell Bash macprogramadores.org

    Pg 22

    Donde hemos puesto el carcter de escape a los caracteres especiales paraque Bash no los interprete.

    Tambin este carcter se usa para poder poner espacios a los nombres deficheros, ya que el espacio es interpretado por Bash como un separador deargumentos de la lnea de comandos, si queremos que no considere elespacio como un cambio de argumento podemos preceder el espacio por \.Por ejemplo el fichero Una historia.avi lo reproduzco en mi ordenadorcon mplayer as:

    $ mplayer Una\ historia.avi

    Si queremos que Bash no interprete el carcter de escape podemosentrecomillarlo '\', o bien hacer que l se preceda a si mismo \\.

    6.3. Entrecomillar los entrecomilladosPodemos usar el carcter de escape para que no se interpreten losentrecomillados simples o dobles, es decir:

    $ echo \"2\*3\>5\" es una expresion cierta"2*3>5" es una expresion cierta$ echo \'2\*3\>5\' es una expresion cierta'2*3>5' es una expresion cierta

    6.4. Texto de varias lneasOtro problema es como escribir un comando que ocupa varias lneas. Bashnos permite utilizar el carcter de escape para ignorar los retornos de carrode la siguiente forma:

    $ echo En un lugar de la Mancha de cuyo nombre no \> quiero acordarme no a mucho tiempo viva un \> hidalgo caballero.En un lugar de la Mancha de cuyo nombre no quiero acordarno a mucho tiempo viva un hidalgo caballero.

    Al pulsar intro Bash nos devuelve el segundo prompt, que por defecto es >, ynos permite seguir escribiendo.

    Una segunda opcin es entrecomillar y no cerrar las comillas, con lo que Bashnos pide que sigamos escribiendo sin necesidad de poner un carcter deescape a los retornos de carro:

    $ echo 'En un lugar de la Mancha de cuyo nombre no

  • El shell Bash macprogramadores.org

    Pg 23

    > quiero acordarme no a mucho tiempo viva un> hidalgo caballero.'En un lugar de la Mancha de cuyo nombre noquiero acordar no a mucho tiempo viva unhidalgo caballero.

    La diferencia est en que en el primer caso los retornos de carro soneliminados, y en el segundo caso no.

  • Tema 2

    Combinacionesde teclas

    Sinopsis:

    Nada es ms til a la hora de manejar de forma frecuente un programa quesaber manejar un buen conjunto de combinaciones de teclas que nos ayudena realizar operaciones frecuentes rpidamente.

    En el caso de Bash es fcil identificar cuando un usuario conoce estascombinaciones de teclas: Nos sorprende ver con que velocidad escribe en suconsola.

    En este tema comentaremos las combinaciones de teclas ms tiles. Lerecomendamos que intente recordarlas y que vuelva a consultar este temacuantas veces haga falta hasta que las utilice de forma mecnica, ver comoaumenta su productividad.

  • El shell Bash macprogramadores.org

    Pg 25

    1. El historial de comandos

    Bash mantiene un histrico de comandos el cual lee al arrancar del ficherosituado en el directorio home .bash_history, durante su ejecucin vaalmacenando en memoria los comandos ejecutados, y al acabar la sesin losescribe al final del fichero .bash_history.

    En principio podemos modificar el fichero que usa Bash para guardar elhistrico indicndolo en la variable de entorno BASH_HISTORY. Aunqueraramente ser til hacer esto.

    Puede usar el comando history para obtener un listado de su historial.

    La forma ms cmoda de referirse a comandos previamente utilizados es usarlas teclas del cursor flecha arriba y flecha abajo. Si an no las conocaprubelas.

    En los siguientes subapartados comentaremos ms a fondo como aprovecharal mximo su histrico de comandos.

    1.1. El comando fc

    El comando fc (fix command) es un clsico del C Shell trado al mundo deBash. fc es un comando tan importante que es un comando interno de Bashque podemos usar para examinar los ltimos comandos, y para editar uno deellos.

    Al ser un comando interno no use man para obtener informacin sobre l,utilice el comando:

    $ help fc

    Podemos obtener un listado de los ltimos comandos usados junto con sunumero usando:

    $ fc -l

    Vemos que este comando es equivalente a history, excepto que lista slolos ltimos comandos del historial y no todos. Para editar uno de ellosindicamos su nmero a fc:

    $ fc 42

    fc abre el comando en el editor que tengamos predefinido en la variableEDITOR y nos permite editarlo.

  • El shell Bash macprogramadores.org

    Pg 26

    El principal problema de diseo que tiene este comando es que al acabar deeditar el comando (al salir del editor) lo ejecuta, comportamiento que puedeser muy peligroso dependiendo del comando que hayamos editado.

    1.2. Ejecutar comandos anterioresLa Tabla 2.1 muestra otro conjunto de comandos internos de Bash (tambinheredados de C Shell) que permiten ejecutar comandos del histrico.

    Comando Descripcin!! Ejecutar el ltimo comando!n Ejecutar el comando nmero n!cadena Ejecutar el ltimo comando que empiece por cadena

    Tabla 2.1: Comandos internos para ejecutar comandos del histrico

    El ms til de ellos es !cadena, ya que con dar las primeras letras de uncomando que hayamos ejecutado previamente lo busca en el historial y loejecuta. Tengase en cuenta que ejecuta el comando ms reciente queempiece por cadena.

    Si hemos consultado el historial, con history o fc -l, podemos ejecutarun comando por nmero usando !n.

  • El shell Bash macprogramadores.org

    Pg 27

    2. Las teclas de control del terminal

    Las teclas de control del terminal son combinaciones de teclas que interpretael terminal (no Bash).

    Podemos preguntar por las teclas de control del terminal usando el comando:

    $ stty allspeed 9600 baud; 24 rows; 80 columns;lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl -echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo -extprociflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixanyimaxbel -ignbrk brkint -inpck -ignpar -parmrkoflags: opost onlcr -oxtabs -onocr -onlretcflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow -dtrflow -mdmbufdiscard dsusp eof eol eol2 erase intr^O ^Y ^D ^? ^Ckill lnext min quit reprint start status^U ^V 1 ^\ ^R ^Q stop susp time werase^S ^Z 0 ^W

    El comando, aparte de darnos ciertos flags sobre distintos aspectos delcomportamiento del terminal, nos muestra las combinaciones de teclas quetenemos asignadas a las tareas ms frecuentes (recurdese que ^X significaCtrl+X). Algunas de estas combinaciones de teclas estn obsoletas, y nomerece mucho la pena recordarlas, pero otras, las que se muestran en laTabla 2.2, si que son muy tiles:

    Combinacinde tecla

    Nombrestty

    Descripcin

    Ctrl+C intr Para el comando actualCtrl+\ quit Fuerza la parada del comando actual (usar si

    Ctrl+C no responde)Ctrl+D eof Final del flujo de entradaCtrl+U kill Borra desde la posicin actual al principio de la

    lneaCtrl+W werase Borra desde la posicin actual al principio de la

    palabra

    Tabla 2.2: Teclas de control del terminal

    Para detener un comando es muy tpico usar la combinacin de teclas Ctrl+C,sta manda un mensaje al programa para que pueda terminar liberando

  • El shell Bash macprogramadores.org

    Pg 28

    correctamente los recursos asignados. Si este programa por alguna razn notermina (ignora el mensaje que le enva Ctrl+C) siempre podemos usarCtrl+\, el cual termina el programa sin esperar a que este libere recursos, conlo que esta combinacin de teclas slo debe ser usada cuando Ctrl+C no hafuncionado.

    Otra combinacin de teclas que ya hemos visto en el apartado 4.1 es Ctrl+D,que nos permita indicar un fin de flujo, cuando el flujo proceda del teclado.

    Las otras combinaciones de teclas que vamos a estudiar en esta seccin sonlas que nos permiten borrar "hacia tras" una palabra Ctrl+W, o toda la fraseCtrl+U. Prubelas en su consola y procure recordar estas combinaciones deteclas, son muy tiles cuando se equivoca o quiere cambiar el comando queest usando.

  • El shell Bash macprogramadores.org

    Pg 29

    3. Modos de edicin en la lnea de comandos

    Por qu no puedo editar mis comandos Bash de la misma forma que editotexto en un editor de texto? Esta es una idea introducida por Bash. Enconcreto existen los modos de edicin de los dos editores ms conocidos enel mundo UNIX: vi y emacs.

    Por defecto Bash utiliza las teclas del modo de edicin de emacs, pero puedecambiar a las teclas del modo de edicin de vi usando el comando:

    $ set -o vi

    Y volver a la combinacin de teclas por defecto con:

    $ set -o emacs

    Nosotros en est seccin veremos slo las teclas de edicin de emacs que sepueden usar tambin en Bash, si no conoce emacs le recomendamos queaprenda a usarlo, porque es, y ser durante muchos aos, un clsico delmundo de UNIX. Si es usted un amante de vi slo le diremos que tiene quepreceder las teclas rpidas por la tecla de escape, y pulsar i para volver aescribir.

    3.1. Moverse por la lneaAlgo que se hace muy a menudo es moverse por la lnea de edicin, puede iral principio y final de la lnea usando las combinaciones de tecla Ctrl+A (ir alprincipio) y Ctrl+E (ir al final), si lo que quiere es moverse una palabra hacaatrs o una palabra hacia adelante utilice Esc+B y Esc+F respectivamente.Tambin puede moverse una letra atrs o adelante con Ctrl+B y Ctrl+F, perodesde que los teclados tienen cursores estas teclas han perdido su utilidadreal. Estas teclas se resumen en la Tabla 2.3.

    Combinacinde teclas

    Descripcin

    Ctrl+A Ir al principio de la lneaCtrl+E Ir al final de la lneaEsc+B Ir una palabra hacia atrs (backward)Esc+F Ir una palabra hacia adelante (forward)Ctrl+B Ir una letra hacia atrsCtrl+F Ir una letra hacia adelante

    Tabla 2.3: Combinaciones de teclas para moverse por la lnea

  • El shell Bash macprogramadores.org

    Pg 30

    3.2. Borrar partes de la lneaOtra operacin que es muy comn es querer borrar partes de la lnea. Lascombinaciones de teclas que vamos a comentar se resumen en la Tabla 2.4.

    En el apartado 2 ya vimos que combinaciones de tecla proporcionaba elterminal, y vimos que con Ctrl+U podamos borrar desde la posicin delcursor al principio de la lnea. Si lo que queremos es borrar hasta el final de lalnea podemos usar la combinacin de tecla emacs Ctrl+K.

    Si lo que queremos es borrar slo desde a posicin actual del cursor hasta elprincipio de la palabra donde estemos situados, vimos que podamos usarCtrl+W. Si lo que queremos es borrar de la posicin del cursor actual hasta elfinal de la palabra donde estemos situados podemos usar Esc+D.

    Para borrar una sola letra es muy tpico que la tecla de borrar haca atrs s que funcione, pero normalmente la tecla DEL no suele funcionar, y en sulugar podemos usar Ctrl+D.

    La ltima operacin de borrado se puede deshacer siempre con la teclaCtrl+Y.

    Combinacinde teclas

    Descripcin

    Ctrl+U Borra de la posicin actual al principio de la lneaCtrl+K Borra de la posicin actual al final de la lneaCtrl+W Borra de la posicin actual al principio de la palabraEsc+D Borra de la posicin actual al final de la palabraCtrl+D Borra el carcter actual hacia adelanteCtrl+Y Deshace el ltimo borrado (Yank)

    Tabla 2.4: Combinaciones de teclas para borrar

    3.3. Buscar en el historialYa comentamos que las teclas del cursor nos permitan movernos por elhistrico de comandos, pero si queremos buscar un determinado comandopodemos usar Ctrl+R, que nos permite buscar haca atrs en el historial uncomando que contenga un determinado texto. Al pulsar esta combinacin deteclas el prompt cambia de forma, y segn vamos escribiendo nos vaindicando el comando del histrico que cumple el patrn dado:

    (reverse-i-search)`yuvs': yuvscaler -O SIZE_600x400 result2.yuv

  • El shell Bash macprogramadores.org

    Pg 31

    Si pulsamos intro se ejecutar el comando actualmente encontrado. Si porcontra pulsamos Esc pasaremos a poder editar el comando encontrado. Porltimo si pulsamos Ctrl+G se abortar la bsqueda y la lnea de edicinquedar limpia. Estas combinaciones de teclas se resumen en la Tabla 2.5.

    Combinacinde teclas

    Descripcin

    Ctrl+R Realiza una bsqueda hacia atrs (Reverse)Intro Ejecuta el comando encontradoEsc Pasa a editar el comando encontradoCtrl+G Cancela la bsqueda y deja limpia la lnea de edicin

    Tabla 2.5: Combinaciones de teclas para bsquedas

    3.4. Autocompletar con el tabuladorUna tecla muy conocida en Bash es el tabulador que nos ayuda a terminar derellenar un comando con el nombre de un comando, de una variable, de unfichero o directorio, o con el nombre de una funcin Bash. Para ello se siguenlas siguientes regla cuando se pulsa el tabulador:

    1. Si no hay nada que empiece por el texto de la palabra que precede alcursor se produce un pitido que informa del problema.

    2. Si hay un comando (en el PATH), una variable (siempre precedida por$), un nombre de fichero o funcin Bash que comienza por el textoescrito, Bash completa la palabra.

    3 . Si hay un directorio que comienza por el nombre escrito, Bashcompleta el nombre de directorio seguido por una barra de separacinde nombres de directorios /.

    4. Si hay ms de una forma de completar la palabra el shell completa loms que puede y emite un pitido informando de que no la pudoterminar de completar.

    5. Cuando Bash no puede completar una cadena (por haber variasposibles que empiezan igual), podemos pulsar dos veces el tabulador yse nos mostrar una lista con las posibles cadenas candidatas.

  • El shell Bash macprogramadores.org

    Pg 32

    4. La librera readline

    La librera readline es una librera GNU que permite editar lneas de textousando los modos de emacs y vi. Aunque originariamente creada por Bash,actualmente la utilizar multitud de comandos GNU. Esto permite estandarizarlas combinaciones de teclas entre muchos comandos.

    readline se puede personalizar usando ficheros de configuracin o bienasignando combinaciones de teclas para la sesin. En los siguientessubapartados estudiaremos cada una de estas formas de configurarla.

    4.1. El fichero de configuracinreadline tiene un fichero de configuracin global que debe ser colocado en/etc/inputrc , y otro para cada usuario que por defecto se llama.inputrc y que se debe colocar en el directorio home de cada usuario.Podemos cambiar este fichero usando la variable de entorno INPUTRC paraindicar una ubicacin distinta.

    Cuando Bash arranca lee estos ficheros (si existen) y carga sus valores.Dentro del fichero puede haber comentarios (precedidos por # ) ,combinaciones de teclas y asignaciones a variables de readline.

    4.1.1. Combinaciones de teclas

    El primer tipo de entradas que puede haber en este fichero son asignacionesde combinaciones de teclas a funciones de readline. Readline tiene unconjunto grande de funciones que podemos encontrar documentadas eninfo readline o en man bash. Estas funciones realizan multitud deoperaciones comunes. Para listar estas variables podemos crear el fichero.inputrc en nuestro directorio home y aadir la siguiente entrada:

    # Lista las funciones y variables de readline"\C-x\C-f": dump-functions"\C-x\C-v": dump-variables

    Como el fichero .inputrc no se lee hasta logarnos de nuevo en Bashpodemos usar la combinacin de teclas Ctrl+X Ctrl+R para que readlinevuelva a leer este fichero.

    Ahora hemos indicado que la combinacin de teclas Ctrl+X Ctrl+F muestre lasfunciones de readline (ejecute la funcin dump-variables() de readline), yque Ctrl+X Ctrl+V muestre las variables de readline.

  • El shell Bash macprogramadores.org

    Pg 33

    Secuencia Descripcin\C- Tecla Ctrl\M- Tecla de escape (Meta)\e Secuencia de escape\\ El carcter \ literal\" El carcter " literal\' El carcter ' literal

    Tabla 2.6: Secuencias usadas en el fichero de configuracin de readline

    La Tabla 2.6 muestra como representar las combinaciones de teclas: Ctrl serepresenta con \C- como hemos visto, la tecla de escape (Meta) con \M-, ypor ltimo si queremos referirnos a teclas especiales podemos usarsecuencias de escape que se representan con \e.

    Por ejemplo, vimos que para borrar una lnea de la posicin del cursor alprincipio de la lnea usbamos Ctrl-U, y para borrarlo de la posicin actual alfinal de la lnea Ctrl+K, pero desafortunadamente por defecto no hay ningunacombinacin de teclas que borre toda la lnea (adelante y atrs). Podemosinventarnos la combinacin de teclas Esc+K, que llama a la funcin kill-whole-line() de readline, modificando el fichero de configuracin dereadline como se muestra ms abajo. Otro problema que tiene el terminal esque normalmente la teclas DEL no funciona correctamente, en este casonecesitamos usar una secuencia de escape para hacer que esta tecla llame ala funcin delete-char() de readline.

    # Borra toda la linea"\M-k": kill-whole-line

    # Borra con la tecla DEL"\e[3~": delete-char

    4.1.2. Variables de readline

    readline tiene una serie de variables, que aparecen documentadas junto conlas funciones de readline (y que tambin puede consultar usando Ctrl+XCtrl+V del ejemplo del apartado anterior), a las cuales podemos asignar unvalor en le fichero de configuracin de readline con set. Por ejemplo, unaopcin que algunas personas encuentran interesante en Mac OS X es evitarque al completar con tabulador distingan minsculas de maysculas. Es decir,si escribimos:

    $ cd mus

    Nos expanda a:

  • El shell Bash macprogramadores.org

    Pg 34

    $ cd Music/

    Para ello podemos aadir la siguiente lnea al fichero de configuracin dereadline:

    # Ignora diferencias de mayusculas/minusculas al# completar con tabuladorset completion-ignore-case on

    4.2. Asignacin de teclas de sesinSi lo que queremos es probar combinaciones de teclas que no queremosalmacenar de forma permanente podemos usar el comando bind, cuyasintaxis es similar a la del fichero de configuracin, pero tenemos queencerrar cada asignacin entre comillas blandas o fuertes. Por ejemplo:

    $ bind "\"\C-x\C-g\": dump-functions"

    Si queremos ver las asignaciones de teclas que hay hechas a cada funcin dereadline podemos usar el comando:

    $ bind -P

    Este comando es muy til para que no asignemos una combinacin de teclasa otra que ya existe. Por ejemplo, en el apartado anterior para sacar lasfunciones de readline creamos la combinacin de teclas Ctrl+X Ctrl+F, pero alusar este comando descubrimos que ya exista la combinacin Ctrl+G quehace lo mismo:

    $ bind -Pdump-functions can be found on "\C-g", "\C-x\C-f".

    De hecho tambin podramos haber sacado las funciones de readline usandoel comando:

    $ bind -l

    Podemos sacar todas las asignaciones de teclas en formato inputrc usandoel comando:

    $ bind -p

    En este caso sera muy til enviar esta salida a un fichero para posterioredicin:

  • El shell Bash macprogramadores.org

    Pg 35

    $ bind -p > .inputrc

    Por ltimo comentar que podemos asignar combinaciones de teclas queejecutan comandos comunes con la opcin -x:

    $ bind -x "\"\C-l\": ls -la"

    Ejecutar ls -la al pulsar Ctrl+L.

  • El shell Bash macprogramadores.org

    Pg 36

    Tema 3

    Personalizar elentorno

    Sinopsis:

    En este tema veremos como hacer el entorno ms agradable personalizandodistintos aspectos de Bash.

    Empezaremos viendo los ficheros que configuran Bash siempre que noslogamos. Tambin veremos como personalizar distintos aspectos delcomportamiento de Bash, y que variables de entornos participan en estapersonalizacin.

    Este es el ltimo tema que dedicamos a aprender a manejar el terminal, elresto del tutorial enseara aspectos ms relativos a la programacin descripts con Bash.

  • El shell Bash macprogramadores.org

    Pg 37

    1. Los ficheros de configuracin de Bash

    Cada vez que nos logamos en la cuenta se ejecuta el contenido del fichero/etc/profile, y luego se mira a ver si en el directorio home existe elfichero .bash_profile, de ser as se ejecuta su contenido para personalizaraspectos de nuestra cuenta.

    Cualquier configuracin que aadamos a .bash_profile no ser efectivahasta que salgamos de la cuenta y volvamos a logarnos, si hacemos cambiosen este fichero y queremos verlos sin salir de la cuenta podemos usar elcomando source, el cual ejecuta el contenido del fichero que le digamos:

    $ source .bash_profile

    Alternativamente al comando source est el comando punto (.), con lo queel contenido de .bash_profile tambin se podra hacer ejecutado as:

    $ . .bash_profile

    Bash permite usar dos nombres alternativos para .bash_profile porrazones de compatibilidad histrica: .bash_login, nombre derivado delfichero .login del C Shell, y .profile nombre usado por el Bourne Shell yel Korn Shell. En cualquier caso, slo uno de estos ficheros ser ejecutado: Si.bash_profile existe los dems sern ignorados, sino Bash comprueba siexiste .bash_login y, slo si ste tampoco existe, comprueba si existe.profile. La razn por la que se eligi este orden de bsqueda es quepodemos almacenar en .profile opciones propias del Bourne Shell, yaadir opciones exclusivas de Bash en el fichero .bash_profile seguidodel comando source .profile para que Bash tambin cargue las opcionesdel fichero .profile.

    .bash_profile se ejecuta slo al logarnos, si abrimos otro shell(ejecutando bash o su) desde la lnea de comandos de Bash lo que seintenta ejecutar es el contenido de .bashrc. Si .bashrc no existe no seejecutan configuraciones adicionales al abrir un nuevo shell. Este esquemanos permite separar configuraciones que se hacen una sola vez, al logarnos,de configuraciones que se cambian cada vez que se abre un nuevo shell. Sihay configuraciones en .bashrc que tambin queremos ejecutar al logarnospodemos poner source .bashrc dentro del fichero .bash_profile.

    Por ltimo, el fichero .bash_logout es un fichero que, de existir, contieneordenes que se ejecutarn al abandonar la cuenta, por ejemplo eliminarficheros temporales o almacenar datos de actividad de usuarios en un ficherode log.

  • El shell Bash macprogramadores.org

    Pg 38

    2. Los alias

    Un alias es un nombre ms corto para un comando que usamos muy amenudo.

    Un ejemplo clsico de alias que se suele encontrar muchas veces en/etc/profile es:

    $ alias ll='ls -laF'

    Ahora podemos usar el alias ll para hacer un listado detallado del directorio.

    Los alias son recursivos con lo que por ejemplo podemos hacer:

    $ alias l='ll'

    Aunque los alias slo pueden ser usados para representar comandos, si porejemplo intentamos representar un directorio largo con un alias, para luegometernos en el con cd, el comando fallar:

    $ alias ASCII='/usr/share/misc/ascii'$ cat ASCIIcat: ASCII: No such file or directory

    Existe un oscuro truco en Bash que permite hacer esto. Si la parte derecha dela asignacin del alias acaba con un espacio, entonces Bash intenta hacersustitucin de alias en la siguiente palabra del comando. Por ejemplo sihacemos:

    $ alias cat='cat '$ cat ASCII

    Obtendremos la tabla ASCII en pantalla.

    Si usamos el comando alias sin parmetros, obtenemos un listado de todoslos alias definidos. Si queremos conocer el valor de un determinado aliaspodemos usar el comando alias seguido del nombre del alias sin smbolo =ni valor.

    $ alias llalias ll='ls -laF'

    Por ltimo, si queremos borrar la definicin de un alias podemos usar elcomando unalias:

    $ unalias ll

  • El shell Bash macprogramadores.org

    Pg 39

    3. Las opciones de Bash

    Las opciones del shell es una forma de poder modificar el comportamiento deste.

    Para fijar estas opciones usamos el comando shopt (shell option). Siejecutamos este comando sin argumentos obtendremos un listado de todaslas opciones del shell y su valor actual.

    Todas estas variables son booleanas y tienen valor de on/off. Podemosactivar estas opciones con shopt -s opcion y desactivarlas con shopt -u opcion.

    La Tabla 3.1 muestra las principales opciones de shopt junto con unadescripcin de su propsito.

    Opcin Descripcincdable_vars Permite que cd use los valores de las variables

    como nombres de directorios.cdspell Ignora pequeos errores en los cambios de

    directorio con cd. Slo en la ejecucininteractiva.

    cmdhist Guarda los comandos que hemos escrito envarias lneas en una sola lnea del historial.

    dotglob Incluye en la expansin de comodines losficheros que empiezan por punto (.).

    expand_aliases Expande un alias cuando lo ejecuta.extglob Utiliza extensiones de los comodines. Vase

    apartado 2.4 del Tema 1. El trmino "glob"tambin se usa a veces para referirse a loscomodines.

    failglob Si falla la expansin de un comodn porque noencuentra nada falla el comando (como hace elC Shell).

    force_fignore Los sufijos especificados en la variable deentorno FIGNORE no se usan para completarpalabras con tabulador.

    hostcomplete Se intenta completar nombres de host al pulsartabulador cuando la palabra contiene una @.

    interactive_comments Permite que dentro de un comando de sesininteractiva haya comentarios (precedidos por #)

    login_shell Variable de slo lectura que indica si Bash hasido lanzado como un shell de login

    nocaseglob Indica si los comodines expanden sinsensibilidad a maysculas/minsculas. Noconfundir con la variable completion-ignore-case de inputrc que lo que hacaera expandir con tabulador.

  • El shell Bash macprogramadores.org

    Pg 40

    ignore-case de inputrc que lo que hacaera expandir con tabulador.

    nullglob Hace que cuando un patrn no encuentraficheros, se expandan por la cadena vaca en vezde por el patrn sin expandir.

    sourcepath Hace que el comando interno source busque elargumento en los directorios que indique PATH

    Tabla 3.1: Principales opciones de shopt

    Una opcin que resulta muy til es cdable_vars, la cual permite que elcomando cd use los valores de las variables como nombres de directorios.Esto se usa cuando hay un directorio al que solemos movernos mucho. Porejemplo si tenemos el directorio /usr/local/mldonkey/incomming alque solemos ir muy a menudo desde la consola podemos definir en losficheros de configuracin de Bash:

    # Para ir a mldonkeyexport DONKEY=/usr/local/mldonkey/incommingshopt -s cdable_vars

    Y ahora para movernos a este directorio basta con hacer:

    $ cd DONKEY

    Obsrvese que DONKEY no va precedida por $.

    Otra opcin muy til es cdspell que permite que se ignoren pequeoserrores en los directorios que indicamos a cd. Por ejemplo este pequeo bailede letras es corregido por cd:

    $ cd /usr/locla/share//usr/local/share/

    Esta opcin slo funciona en modo interactivo.

  • El shell Bash macprogramadores.org

    Pg 41

    4. Las variables de entorno

    Las variables de entorno nos ayudan a configurar el entorno en el que seejecutan los programas.

    Para declararlas es importante recordar que las variables de entorno nopueden tener espacios, y si queremos asignar un valor con espacio debemosde entrecomillarlo, o bien preceder el espacio por un carcter de escape:

    $ NOMBRE='Fernando Lopez'$ echo $NOMBREFernando Lopez$ NOMBRE=Fernando\ Lopez$ echo $NOMBREFernando Lopez

    Como sabemos, para obtener el valor de una variable debemos de precederlapor $. Obsrvese que las comillas o el carcter de escape no forman parte delvalor de la variable una vez que se realiza la asignacin.

    Para eliminar una variable de entorno podemos usar el comando unset. Porejemplo:

    $ unset NOMBRE

    4.1. Variables y entrecomilladoEn el apartado 6.1 del Tema 1 comentamos que las comillas dobles (lasdbiles) interpretaban algunos de los caracteres que contenan. Uno de elloses el carcter $, el cual nos permite expandir el valor de una variable dentrode una cadena. Por ejemplo:

    $ articulo='Zapatos negros'$ precio=20.5$ echo "El articulo $articulo cuesta $precio euros"El articulo Zapatos negros cuesta 20.5 euros

    4.2. Personalizar el promptPodemos personalizar el prompt de Bash usando las variables de entornoPS1, PS2, PS3 y PS4. La Tabla 3.2 muestra las opciones de personalizacinque podemos usar en cualquiera de los prompt.

  • El shell Bash macprogramadores.org

    Pg 42

    En el prompt podemos encontrar mucha opciones que nos ayudan a trabajar,quiz la ms usada es \w que muestra le directorio donde estamos situadosen cada momento.

    $ PS1='\w->'~->

    Donde ~ significa que estamos en el directorio home.

    Es muy tpico querer saber si somos root o cualquier otro usuario de lamquina, para lo cual se usa la opcin \$ que muestra una # si somos root, oun $ en cualquier otro caso.

    ~->PS1='\w\$'~$

    Muchas veces el prompt nos ayuda a saber en que mquina estamossituados, esto es til por ejemplo cuando tenemos la costumbre de hacermuchos telnet o ssh a otras mquinas. En este caso podemos usar la opcin\H que nos da el nombre de la mquina donde estamos situados, o la opcin\h que nos da el nombre de la mquina slo hasta el primer punto:

    ~$ PS1='\h\w\$'macbox~$ PS1='\H\w\$'macbox.macprogramadores.org~$

    Aunque en Mac OS X no es muy til, cuando trabajamos con una mquinaUNIX en modo slo consola solemos poder movernos por un conjunto de 6terminales virtuales usando las teclas Ctrl+F1 hasta Ctrl+F6 (o Alf+F1 hastaAlf+F6 en algunas configuraciones). En estos casos s que es recomendableconocer el nombre del terminal con la opcin \l. Por ejemplo en mi FreeBSDtengo este prompt:

    [root@freebsd@ttyv0]~# echo $PS1[\u@\h@\l]\w\$

    Donde me indica el usuario con el que estoy logado (opcin \u), la maquinadonde estoy, y el terminal virtual donde estoy trabajando.

    En mi Mac OS X tengo este otro prompt:

    $ echo $PS1[\u@\h]\w\$[fernando@macbox]~$

    Donde me indica el usuario con el que estoy logado y el host, pero no elterminal virtual.

  • El shell Bash macprogramadores.org

    Pg 43

    Si estamos trabajando con el comando fc (vase apartado 1.1 del Tema 2)podra ser til usar \! que nos va dando el nmero histrico del comandoque vamos a ejecutar.

    Opcin Descripcin\a El carcter ASCII bell (007)\A La hora en formato HH:MM\d La fecha en formato semana mes dia\D {formato} Nos permite personalizar ms la fecha\e El carcter de escape ASCII (033)\H Hostname\h El nombre de la mquina hasta el primer punto\j Nmero de jobs hijos del shell\l Nombre del terminal en el que estamos trabajando (p.e.

    ttyp2)\n Retorno de carro y nueva lnea\r Retorno de carro\s Nombre del shell\t Hora en formato HH:MM:SS con 12 horas\T Hora en el formato anterior pero con 24 horas\u Nombre de usuario\v Versin de Bash\w Ruta del directorio actual\W Nombre del directorio actual (sin ruta)\# Nmero de comandos ejecutados\! Nmero histrico del comando\$ # si somos root, o $ en caso contrario\nnn Cdigo de carcter a mostrar en octal\\ La barra haca atrs\[ Empieza una secuencia de caracteres no imprimibles, como

    los caracteres de control de secuencias del terminal\] Acaba una secuencia de caracteres no imprimibles

    Tabla 3.2: Opciones de personalizacin del prompt

    PS2 es el prompt secundario y por defecto vale >. Se usa cuando escribimosun comando inacabado, por ejemplo vimos:

    $ echo En un lugar de la Mancha de cuyo nombre no \> quiero acordarme no a mucho tiempo viva un \> hidalgo caballero.En un lugar de la Mancha de cuyo nombre no quiero acordarno a mucho tiempo viva un hidalgo caballero.

    Por ltimo, PS3 y PS4 son prompts de programacin y depuracin queestudiaremos en temas posteriores.

  • El shell Bash macprogramadores.org

    Pg 44

    4.3. Variables de entorno internasExisten una serie de variables de entorno, las cuales se resumen en la Tabla3.3, que no las fijamos nosotros sino que las fija el shell, y cuyo valor es deslo lectura.

    Variable DescripcinSHELL Path del fichero que estamos usandoLINES Lneas del terminal en caracteresCOLUMNS Columnas del terminal en caracteresHOME Directorio home del usuarioPWD Directorio actualOLDPWD Anterior directorio actualUSER Nombre de usuario en la cuenta donde estamos logados

    Tabla 3.3: Variables de entorno internas

    Algunas variables se actualizan dinmicamente, por ejemplo LINES yCOLUMNS en todo momento almacenan en nmero de filas y columnas de lapantalla, y las usan algunos programas como vi o emacs para modificar suapariencia.

    4.4. Exportar variablesLas variables de entorno que definimos dentro de una sesin de Bash noestn disponibles para los subprocesos que lanza Bash (slo las puede usarBash y nuestros comandos interactivos y scripts) a no ser que las exportemoscon el comando export. Por ejemplo:

    $ EDITOR=/sw/bin/joe$ export EDITOR

    Tambin podemos exportar una variable de entorno a la vez que laasignamos un valor as:

    $ export EDITOR=/sw/bin/joe

    Podemos obtener un listado de las variables exportadas usando el comandoenv o el comando export sin argumentos. Para obtener las variables tantoexportadas como no exportadas debemos usar el comando set sinargumentos.

  • El shell Bash macprogramadores.org

    Pg 45

    Tema 4

    Programacinbsica del shell

    Sinopsis:

    Este tema introduce los conceptos ms bsicos de la programacin de scriptsy funciones con Bash.

    En este momento debera de ser capaz de manejarse con el terminal (el modointeractivo) con ms soltura que antes de leer este tutorial. Ahorapretendemos empezar a entender los scripts que configuran su mquina, y aque sea capaz de crear sus propios scripts.

    El tema supone que el lector conoce los conceptos bsicos de programacinen algn lenguaje estructurado (C, Pascal, Basic). Bash no usa los conceptosde programacin orientada a objetos, pero si conoce este tipo deprogramacin (p.e. Java) tambin le servir aqu, ya que la programacinestructurada es un subconjunto de la orientada a objetos.

    Bash es un lenguaje muy crptico, con lo que sera recomendable que se fijarabien en la sintaxis, y que intentara hacer los ejercicios que proponemos en suordenador con el fin de consolidad las ideas bsicas que vamos a desarrollaren este tema.

  • El shell Bash macprogramadores.org

    Pg 46

    1. Scripts y funciones

    1.1. ScriptsUn script es un fichero que contiene comandos Bash ejecutables. Losficheros de configuracin de Bash como .bash_profile o .bashrc, vistosen el apartado 1 del Tema 3, son ejemplos de scripts.

    Para crear un script use su editor de texto favorito, y guardelo en un fichero.Una vez creado el script existen dos formas de ejecutarlo:

    La primera consiste en ejecutarlo con el comando source fichero, el cualcarga el fichero en la memoria de Bash y lo ejecuta.

    La segunda forma implica poner al fichero permiso de ejecucin (con elcomando chmod +x fichero). Una vez puesto este permiso, podremosejecutarlo siempre que est en alguno de los directorios indicados en lavariable de entorno PATH. De hecho muchos comandos comunes (p.e. spello man) estn implementados como scripts Bash, y no como programas Cejecutables. Es muy tpico en este caso empezar el script poniendo en laprimera lnea #! /bin/bash, de esta forma indicamos que el script se debeejecutar con Bash, a pesar de que Bash no fuera el shell por defecto. Otrosscripts para otros lenguajes como awk, ksh o perl tambin se escribenempezando la primera lnea por el path del shell a utilizar.

    Hay otra diferencia entre estas dos formas de ejecutarlo: Cuando ejecutamosun script con source, ste se ejecuta dentro del proceso del shell, mientrasque si lo ejecutamos como un fichero ejecutable se ejecuta en un subshell.Esto implica que slo las variables de entorno exportadas son conocidas porel nuevo subshell que ejecuta el programa.

    De hecho, cada vez que un script llama a un comando tambin se ejecuta enun proceso aparte, excepto con los comandos internos que se ejecutandentro del proceso del script, lo cual les hace ms rpidos y les permiteacceder a las variables de entorno no exportadas.

    1.2. FuncionesLas funciones de Bash son una extensin de las funciones que existen desdeel Bourne Shell.

    stas, a diferencia de los scripts, se ejecutan dentro de la memoria del propioproceso de Bash, con lo que son ms eficientes que ejecutar scripts aparte,pero tienen el inconveniente de que tienen que estar siempre cargadas en la

  • El shell Bash macprogramadores.org

    Pg 47

    memoria del proceso Bash para poder usarse. Actualmente, debido a la grancantidad de memoria que tienen los ordenadores, el tener funciones cargadasen la memoria de Bash tiene un coste insignificante, con lo que no debera depreocuparle el tener cargadas gran cantidad de estas en su entorno.

    Para definir una funcin existen dos formatos:

    El estilo del Bourne Shell;

    function nombrefn{ comandos bash }

    O el estilo del C Shell:

    nombrefn(){ comandos bash }

    No existe diferencia entre ellos, y usaremos ambos indistintamente. Paraborrar una funcin podemos usar el comando unset -f nombrefn.

    Cuando definimos una funcin se almacena como una variable de entorno(con su valor almacenando la implementacin de la funcin). Para ejecutar lafuncin simplemente escribimos su nombre seguido de argumentos, comocuando ejecutamos un comando. Los argumentos actan como parmetrosde la funcin.

    Podemos ver que funciones tenemos definidas en una sesin usando elcomando declare -f. El shell imprime las funciones, y su definicin,ordenadas alfabticamente. Si preferimos obtener slo el nombre de lasfunciones podemos usar el comando declare -F.

    Si una funcin tiene el mismo nombre que un script o ejecutable, la funcintiene preferencia: Esta regla se ha usado muchas veces para, engaando alos usuarios, violar la integridad de su sistema.

    1.3. Orden de preferencia de los smbolos de BashA continuacin se enumera el orden de preferencia que sigue Bash a la horade resolver un smbolo:

    1. Alias.2. Palabras clave (keywords) como function, if o for.3. Funciones4. Comandos internos (p.e. cd o type).5. Scripts y programas ejecutables, para los cuales se sigue el orden en

    que se dan sus directorios en la variable de entorno PATH.

  • El shell Bash macprogramadores.org

    Pg 48

    Aunque no es muy comn, a veces conviene cambiar estos ordenes usandolos comandos internos command, builtin y enable. Esto nos permite teneralias y scripts con el mismo nombre y elegir cual de ellos ejecutar. Enposteriores temas veremos su utilidad.

    Si nos interesa conocer la procedencia de un comando podemos usar elcomando interno type. Si le damos un comando nos indica cual es su fuente,si le damos varios nos indica la fuente de cada no de ellos. Por ejemplo:

    $ type lsls is /bin/ls$ type ls llls is /bin/lsll is aliased to `ls -laF'

    Si tenemos un script, una funcin y un alias llamados hazlo, type nos dirque est usando hazlo como alias, ya que los alias tienen preferencia sobreel resto de smbolos:

    $ type hazlohazlo is aliased to `rm *'

    type tambin tiene opciones que nos permiten obtener detalles de unsmbolo. Si queremos conocer todas las definiciones de un smbolo podemosusar type -a. Por ejemplo:

    $ type -a hazlohazlo is aliased to `rm *'hazlo is a functionhazlo (){ rm *}hazlo is ./hazlo

    Podemos conocer el tipo de un smbolo con la opcin -t: Nos devolveralias, keyword, function, builtin o file. Por ejemplo:

    $ type -t cdbuiltin$ type -t cpfile

  • El shell Bash macprogramadores.org

    Pg 49

    2. Variables del shell

    Principalmente Bash utiliza variables de tipo cadena de caracteres. Esto lediferencia de otros lenguajes de programacin donde las variables tienendistintos tipos. Aunque ste es el tipo por defecto de las variables de Bash,ms adelante veremos que las variables en Bash tambin pueden tener otrostipos, como por ejemplo enteros con los que realizar operaciones aritmticas.

    Por convenio las variables de entorno exportadas (las que pasamos a lossubprocesos) se escriben en maysculas, y las que no exportamos enminsculas. Esta regla, ms que por el modo interactivo, es especialmenteseguida por los scripts y funciones que vamos a empezar a programar ahora.

    2.1. Los parmetros posicinalesLos parmetros posicinales son los encargados de recibir los argumentosde un script y los parmetros de una funcin. Sus nombres son 1, 2, 3, etc.,con lo que para acceder a ellos utilizaremos, como normalmente, el smbolo $de la forma $1, $2, $3, etc. Adems tenemos el parmetro posicional 0 quealmacena el nombre del script donde se ejecuta.

    Por ejemplo imaginemos que creamos el script del Listado 4.1:

    #!/bin/bash# Ejemplo de script que recibe parametros y los imprime

    echo "El script $0"echo "Recibe los argumentos $1 $2 $3 $4"

    Listado 4.1: Script que recibe argumentos

    Si lo hemos guardado en un fichero llamado recibe con el permiso xactivado podemos ejecutarlo as:

    $ recibe hola adiosEl script ./recibeRecibe los argumentos hola adios

    Como los argumentos $3 y $4 no los hemos pasado son nulos que dan lugara una cadena vaca que no se imprime.

    Para definir una funcin podemos escribirla en un fichero y cargarla en elshell usando el comando source, o bien definirla directamente en modointeractivo:

  • El shell Bash macprogramadores.org

    Pg 50

    $ function recibe> {> echo "La funcion $0"> echo "Recibe los argumentos $1 $2 $3 $4"> }$ recibe buenos dias BashLa funcion -bashRecibe los argumentos buenos dias Bash

    Como los nombres de funciones tienen preferencia sobre los de los scriptsahora se ejecuta la funcin recibe() y no el script recibe. Vemos queahora $0 no se ha sustituido por el nombre de la funcin sino por -bash,esto es as porque $0 siempre se sustituye por el nombre de script (no el dela funcin), o -bash si lo ejecutamos directamente desde la lnea decomandos.

    Por ltimo comentar que no podemos modificar el valor de las variablesposicinales, slo se pueden leer, si intentamos asignarlas un valor seproduce un error.

    2.2. Variables locales y globalesPor defecto los parmetros posicinales son locales al script o funcin y no sepueden acceder o modificar desde otra funcin. Por ejemplo en el Listado 4.2vemos un script, que guardaremos en el fichero saluda, que llama a unafuncin para que salude al nombre que pasamos al script como argumento en$1:

    # Script que llama a una funcion para saludar

    function DiHola{ echo "Hola $1"}

    DiHola

    Listado 4.2: Script que llama a una funcin para saludar

    Al ejecutarlo obtenemos:

    $ saluda FernandoHola

    Vemos que el argumento pasado en $1 no a sido cogido por la funcin, esoes porque $1 es local al script, y si queremos que lo reciba la funcintendremos que pasrselo como muestra el Listado 4.3.

  • El shell Bash macprogramadores.org

    Pg 51

    # Script que llama a una funcion para saludar

    function DiHola{ echo "Hola $1"}

    DiHola $1

    Listado 4.3: Script que pasa el argumento a una funcin para que salude

    A diferencia de los parmetros posicinales, el resto de variables quedefinimos en un script o funcin son globales, es decir una vez definidas en elscript son accesibles (y modificables) desde cualquier funcin. Por ejemplo,en el Listado 4.4 se muestra un script llamado dondeestoy, en el que lavariable donde est definida por el script y modificada por la funcin.

    # Ejemplo de variable global

    function EstasAqui{ donde='Dentro de la funcion'}

    donde='En el script'echo $dondeEstasAquiecho $donde

    Listado 4.4: Ejemplo de variable global

    Al ejecutarlo obtenemos:

    $ dondeestoyEn el scriptDentro de la funcion

    Si queremos que una variable no posicional sea local debemos de ponerla elmodificador local, el cual slo se puede usar dentro de las funciones (no enlos scripts). Por ejemplo en el Listado 4.5 ahora la funcin se crea su propiavariable local donde y no modifica la global del script.

    # Ejemplo de variable global

    function EstasAqui{ local donde='Dentro de la funcion'}

  • El shell Bash macprogramadores.org

    Pg 52

    donde='En el script'echo $dondeEstasAquiecho $donde

    Listado 4.5: Ejemplo de variable local y global con el mismo nombre

    Al ejecutarlo obtenemos:

    $ dondeestoyEn el scriptEn el script

    Por ltimo comentar que las variables globales tambin se pueden definirdentro de una funcin. Por ejemplo, en el Listado 4.6 se muestra comodefinimos la variable global quiensoy dentro de la funcin EstasAqui() yla usamos ms tarde desde el script.

    # Ejemplo de variable global

    function EstasAqui{ local donde='Dentro de la funcion' quiensoy=Fernando}

    donde='En el script'echo $dondeEstasAquiecho $dondeecho "Soy $quiensoy"

    Listado 4.6: Ejemplo de variable global definida dentro de una funcin

    Al ejecutar el script del Listado 4.6 obtenemos:

    $ dondeestoyEn el scriptEn el scriptSoy Fernando

    2.3. Las variables $*, $@ y $#

    La variable $# almacena el nmero de argumentos o parmetros recibidospor el script o la funcin. El valor es de tipo cadena de caracteres, pero msadelante veremos como podemos convertir este valor a nmero para operarcon l.

  • El shell Bash macprogramadores.org

    Pg 53

    Tanto $* como $@ nos devuelven los argumentos recibidos por el script ofuncin.

    Como ejemplo, el script recibe del Listado 4.1 lo vamos a modificar talcomo muestra el Listado 4.7 para que use esta variable para sacar losargumentos recibidos.

    Ejemplo de script que recibe parametros y los imprime

    echo "El script $0 recibe $# argumentos:" $*echo "El script $0 recibe $# argumentos:" $@

    Listado 4.7: Ejemplo de uso de $* y $@

    Al ejecutarlo obtenemos:

    $ recibe hola adiosEl script ./recibe recibe 2 argumentos: hola adiosEl script ./recibe recibe 2 argumentos: hola adios

    Aunque cuando no entrecomillamos $* o $@ no existen diferencias entre usaruno y otro, cuando los encerramos entre comillas dbiles existen dosdiferencias que conviene resaltar:

    La primera es que podemos cambiar el smbolo que usa $* para separar losargumentos indicndolo en la variable de entorno IFS (Internal FieldSeparator), mientras que $@ siempre usa como separador un espacio. Porejemplo si hacemos el siguiente script:

    IFS=','echo "El script $0 recibe $# argumentos: $*"echo "El script $0 recibe $# argumentos: $@"

    Al ejecutarlo obtenemos:

    $ recibe hola adiosEl script ./recibe recibe 2 argumentos: hola,adiosEl script ./recibe recibe 2 argumentos: hola adios

    La segunda diferencia se produce al recoger los argumentos para pasrselosa una funcin. Imaginemos que tenemos definida la siguiente funcin:

    function CuentaArgumentos{ echo "Recibidos $# argumentos"}

  • El shell Bash macprogramadores.org

    Pg 54

    Ahora podemos pasar los argumentos recibidos por el script a la funcinusando cualquiera de las dos variables:

    CuentaArgumentos $*CuentaArgumentos $@

    Y al ejecutarlo obtenemos:

    $ recibe hola adiosRecibidos 2 argumentosRecibidos 2 argumentos

    Pero el no encerrar tanto $* como $@ entre comillas al llamar a una funcintiene un efecto lateral por el que no se recomienda. Este efecto se producecuando recibimos argumentos que contienen espacios:

    $ recibe "El perro" "La casa"Recibidos 4 argumentosRecibidos 4 argumentos

    El problema est en que se pierden las comillas de las variables y seinterpreta cada palabra como un parmetro de la funcin.

    Sin embargo, si entrecomillamos $* y $@:

    CuentaArgumentos "$*"CuentaArgumentos "$@"

    Obtenemos el siguiente resultado:

    $ recibe "El perro" "La casa"Recibidos 1 argumentosRecibidos 2 argumentos

    Es decir, entrecomillar $* tiene el efecto de que se convierte en una solapalabra, mientras que si entrecomillamos $@ cada argumento es una palabra.

    En consecuencia obtenemos las siguentes reglas generales:

    1. Siempre conviene entrecomillar las variables $* y $@ para evitar quelos argumentos que contengan espacios sean mal interpretados.

    2 . Si queremos cambiar el delimitador que separa los argumentos(usando IFS) debemos utilizar @* entrecomillado.

    3. Si lo que queremos es pasar los argumentos a una funcin debemos deusar $@ entrecomillado.

  • El shell Bash macprogramadores.org

    Pg 55

    2.4. Expansin de variables usando llavesRealmente la forma que usamos para expandir una variable $variable esuna simplificacin de la forma ms general ${variable}. La simplificacinse puede usar siempre que no existan ambigedades. En este apartadoveremos cuando se producen las ambigedades que nos obligan a usar laforma ${variable}.

    La forma ${variable} se usa siempre que la variable vaya seguida por unaletra, dgito o guin bajo (_), en caso contrario podemos usar la formasimplificada $variable. Por ejemplo si queremos escribir nuestro nombre(almacenado en la variable nombre) y nuestro apellido (almacenado en lavariable apellido) separados por un guin podramos pensar en hacer:

    $ nombre=Fernando$ apellido=Lopez$ echo "$nombre_$apellido"Lopez

    Pero esto produce una salida incorrecta porque Bash ha intentado buscar lavariable $nombre_ que al no existir la ha expandido por una cadena vaca.

    Para solucionarlo podemos usar las llaves:

    $ echo "${nombre}_$apellido"Fernando_Lopez

    Otro lugar donde necesitamos usar llaves es cuando vamos a sacar el dcimoparmetro posicional. Si usamos $10, Bash lo expandir por $1 seguido deun 0, mientras que si usamos ${10} Bash nos dar el dcimo parmetroposicional.

  • El shell Bash macprogramadores.org

    Pg 56

    3. Operadores de cadena

    Los operadores de cadena nos permiten manipular cadenas sin necesidadde escribir complicadas rutinas de procesamiento de texto. En particular losoperadores de cadena nos permiten realizar las siguientes operaciones:

    Asegurarnos de que una variable existe (que est definida y que no esnula).

    Asignar valores por defecto a las variables. Tratar errores debidos a que una variable no tiene un valor asignado Coger o eliminar partes de la cadena que cumplen un patrn

    Vamos a empezar viendo los operadores de sustitucin, para luego ver los debsqueda de cadenas.

    3.1. Operadores de sustitucinLa Tabla 4.1 muestra los operadores de sustitucin.

    Operador Descripcin$ {var:-valor} 1 Si var existe y no es nula retorna su valor,

    sino retorna valor.$ {var:+valor} 1 Si var existe y no es nula retorna valor,

    sino retorna una cadena nula.$ {var:=valor} 1 Si var existe y no es nula retorna su valor,

    sino asigna valor a variable y retornasu valor.

    $ {var:?mensaje} 1 Si var existe y no es nula retorna su valor,sino imprime var:mensaje y aborta elscript que se est ejecutando (slo enshells no interactivos). Si omitimosmensaje imprime el mensaje por defectoparameter null or not set.

    $ {var:offset:longitud} Retorna una subcadena de var queempieza en offset y tiene longitudcaracteres. El primer carcter de varempieza en la posicin 0. Si se omitelongitud la subcadena empieza enoffset y continua hasta el final de var.

    Tabla 4.1: Operadores de sustitucin

    1 Los dos puntos (:) en este operador son opcionales. Si se omiten en vez de comprobar siexiste y no es nulo, slo comprueba que exista (aunque sea nulo).

  • El shell Bash macprogramadores.org

    Pg 57

    $ {var:-valor} se utiliza para retornar un valor por defecto cuando elvalor de la variable var est indefinido. Por ejemplo ${veces:-1} devuelve1 si el valor de veces est indefinido o es nulo.

    $ {var:+valor} por contra se utiliza para comprobar que una variabletenga asignado un valor no nulo. Por ejemplo ${veces:+1} retorna 1 (quese puede interpretar como verdadero) si veces tiene un valor asignado.

    Los dos operadores de cadena anteriores no modifican el valor de la variablevar, simplemente devuelven un valor, si queremos modificar var podemosusar $ {var:=valor} que asigna un valor a la variable si sta estindefinida. Por ejemplo $ {veces:=1} asigna 1 a veces si sta no tienevalor.

    Tambin podemos querer detectar errores producidos porque una variable notenga valor asignado, en este caso usamos $ {var:?mensaje} que detectasi var no tiene valor asignado y produce un mensaje de error. Por ejemplo ${veces:?'Debe tener un valor asignado'} imprime veces: Debetener un valor asignado si veces no tiene valor asignado.

    Por ltimo podemos coger partes de una cadena usando $ {var:offset:longitud} . Por ejemplo si nombre vale Fernando Lopez, ${nombre:0:8} devuelve Fernando y $ {nombre:9} devuelve Lopez.

    Ejercicio 4.1

    Imaginemos que tenemos un fichero con el saldo y nombre de un conjuntode clientes de la forma:

    $ cat clientes45340 Jose Carlos Martinez24520 Mari Carmen Gutierrez450 Luis Garcia Santos44 Marcos Vallido Grandes500 Carlos de la Fuente Lopez

    Escribir un script que imprima los N clientes que ms saldo tengan. El scriptrecibir como primer argum