436
El shell Bash

bash.docx

Embed Size (px)

Citation preview

El shell Bash

El shell BashMacProgramadores

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 ejemplosdeberanserexactamenteigualdetilesenotrossistemasUNIX.Cuandoexistandiferenciaslasindicaremosparaqueusuariosdeotrossistemaspuedan seguir correctamente este documento.

El tutorial asume que el lector conoce los aspectos ms bsicos de qu es, yparaqusirveunterminal.Alolargodeldocumentocomentaremosgrancantidad de comandos que estn relacionados con el shell, y que ayudan ahacer que los ejemplos resulten tiles. Sin embargo, resulta imposible abarcartodoslosmuchosytilescomandosalosquepodemosaccederdesdeelterminal.

Al acabar este tutorial el lector debera de haber aprendido a personalizar suterminal para hacerlo ms manejable, a modificar o crear los scripts que con-figuran su sistema y a manipular texto mediante el uso de comandos comogrep, sed y awk.

Nota legal

Este tutorial ha sido escrito por Fernando Lpez Hernndez para MacProgra-madores, y de acuerdo a los derechos que le concede la legislacin espaolae internacional el autor prohbe la publicacin de este documento en cualquierotro servidor web, as como su venta, o difusin en cualquier otro medio sinautorizacin previa.

Sin embargo el autor anima a todos los servidores web a colocar enlaces aeste documento. El autor tambin anima a bajarse o imprimirse este tutorial acualquierpersonainteresadaenconocerelshellBash,ylasventajasqueaporta tanto al usuario como al programador.

Madrid, Mayo 2009Para cualquier aclaracin contacte con:[email protected]

Pg 2

El shell BashMacProgramadores

Tabla de contenido

TEMA 1: Introduccin a Bash

1.El shell que estamos usando ................................................................82.Expansin de nombres de ficheros y directorios...................................102.1.Los comodines ............................................................................102.2.El comodn tilde ..........................................................................112.3.El comodn llaves ........................................................................122.4.Comodines extendidos.................................................................133.Los comandos internos de Bash..........................................................154.Redirecciones y pipes ........................................................................164.1.Operadores de redireccin ...........................................................164.2.Pipes ..........................................................................................175.Ejecucin secuencial y concurrente de comandos ................................186.Caracteres especiales y entrecomillado ...............................................196.1.Entrecomillado ............................................................................196.2.Caracteres de escape ..................................................................206.3.Entrecomillar los entrecomillados..................................................216.4.Texto de varias lneas..................................................................21

TEMA 2: Combinaciones de teclas

1.El historial de comandos ....................................................................241.1.El comando fc............................................................................241.2.Ejecutar comandos anteriores ......................................................252.Las teclas de control del terminal........................................................263.Modos de edicin en la lnea de comandos ..........................................273.1.Moverse por la lnea ....................................................................273.2.Borrar partes de la lnea ..............................................................283.3.Buscar en el historial ...................................................................293.4.Autocompletar con el tabulador....................................................294.La librera readline.............................................................................304.1.El fichero de configuracin...........................................................304.2.Asignacin de teclas de sesin .....................................................32

TEMA 3: Personalizar el entorno

1.Los ficheros de configuracin de Bash.................................................352.Los alias ...........................................................................................363.Las opciones de Bash ........................................................................374.Las variables de entorno ....................................................................394.1.Variables y entrecomillado ...........................................................394.2.Personalizar el prompt .................................................................394.3.Variables de entorno internas.......................................................424.4.Exportar variables .......................................................................42

Pg 3

El shell BashMacProgramadores

TEMA 4: Programacin bsica del shell

1.Scripts y funciones ............................................................................441.1.Scripts........................................................................................441.2.Funciones ...................................................................................441.3.Orden de preferencia de los smbolos de Bash...............................452.Variables del shell..............................................................................472.1.Los parmetros posicinales.........................................................472.2.Variables locales y globales ..........................................................482.3.Las variables $*, $@ y $#............................................................502.4.Expansin de variables usando llaves............................................533.Operadores de cadena.......................................................................543.1.Operadores de sustitucin............................................................543.2.Operadores de bsqueda de patrones...........................................573.3.El operador longitud ....................................................................604.Sustitucin de comandos ...................................................................61

TEMA 5: Control de flujo

1.Las sentencias condicionales ..............................................................671.1.Las sentencias if, elif y else..................................................671.2.Los cdigos de terminacin ..........................................................671.3.Las sentencias return y exit....................................................681.4.Operadores lgicos y cdigos de terminacin ................................701.5.Test condicionales.......................................................................712.El bucle for .....................................................................................773.Los bucles while y until................................................................814.La sentencia case.............................................................................825.La sentencia select.........................................................................84

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

1.Opciones de la lnea de comandos ......................................................871.1.La sentencia shift ....................................................................871.2.El comando interno getopts ......................................................892.Variables con tipo..............................................................................923.Expresiones aritmticas .....................................................................953.1.Similitud con las expresiones aritmticas C....................................953.2.El comando interno let ..............................................................963.3.Sentencias de control de flujo aritmticas .....................................983.4.Arrays ...................................................................................... 100

Pg 4

El shell BashMacProgramadores

TEMA 7: Redirecciones

1.Redirecciones.................................................................................. 1071.1.Los descriptores de fichero ........................................................ 1081.2.El comando exec...................................................................... 1101.3.Here documents........................................................................ 1112.Entrada y salida de texto ................................................................. 1132.1.El comando interno echo .......................................................... 1132.2.El comando interno printf ...................................................... 1152.3.El comando interno read .......................................................... 1183.Los bloques de comandos ................................................................ 1214.Los comandos comand, builtin y enable .................................... 1245.El comando interno eval ................................................................ 125

TEMA 8: Manipular texto

1.Herramientas de manipulacin de texto ............................................ 1291.1.Edicin de stream con sed ......................................................... 1291.2.Generacin de informes con awk................................................ 1322.Expresiones regulares...................................................................... 1372.1.Caracteres y metacaracteres ...................................................... 1372.2.Los metacaracteres posicionales................................................. 1392.3.Extensin de la expresin regular ............................................... 1392.4.Agrupar expresiones regulares y alternativas............................... 1403.Programacin con sed ..................................................................... 1413.1.El pattern space y holding space ................................................ 1413.2.Direccionamiento ...................................................................... 1413.3.Agrupar procedimientos............................................................. 1443.4.Comentarios ............................................................................. 1453.5.El procedimiento de sustitucin .................................................. 1463.6.Procedimientos para insertar, aadir y cambiar ........................... 1493.7.Imprimir el nmero de lnea....................................................... 1503.8.Leer y escribir ficheros............................................................... 1513.9.Control de flujo bsico ............................................................... 1533.10.Pattern space multilnea........................................................... 1543.11.Holding space ......................................................................... 1593.12.Control de flujo avanzado ........................................................ 1634.Programacin con awk..................................................................... 1654.1.El bucle de proceso ................................................................... 1654.2.Variables del sistema................................................................. 1664.3.Expresiones .............................................................................. 1704.4.Formatear la salida.................................................................... 1724.5.Paso de variables como argumentos ........................................... 1734.6.Sentencias de control de flujo .................................................... 1744.7.Arrays ...................................................................................... 1754.8.Variables del sistema que son arrays .......................................... 1814.9.Funciones ................................................................................. 182

Pg 5

El shell BashMacProgramadores

4.10.Redirecciones y pipes .............................................................. 184

TEMA 9: Control de procesos

1.IDs de procesos y nmeros de jobs .................................................. 1912.Control de jobs................................................................................ 1922.1.Foreground y background .......................................................... 1922.2.Suspender y reanudar un job ..................................................... 1932.3.El comando ps.......................................................................... 1942.4.El comando top........................................................................ 1963.Seales........................................................................................... 1973.1.Combinaciones de teclas que envan seales ............................... 1983.2.El comando interno kill .......................................................... 1984.Capturar seales desde un script ...................................................... 2004.1.El comando interno trap .......................................................... 2004.2.Traps y funciones...................................................................... 2014.3.IDs de proceso.......................................................................... 2024.4.Ignorar seales ......................................................................... 2035.Reatachar sesiones del terminal ....................................................... 2056.Corutinas ........................................................................................ 2067.Subshells ........................................................................................ 2088.La sustitucin de procesos ............................................................... 209

TEMA 10: Depurar scripts

1.Opciones de Bash para depuracin ................................................... 2112.Fake signals.................................................................................... 2132.1.La seal SIGEXIT..................................................................... 2132.2.La seal SIGERR....................................................................... 2142.3.La seal SIGDEBUG................................................................... 2152.4.La seal SIGRETURN................................................................. 2153.Un depurador Bash.......................................................................... 2163.1.Estructura del depurador ........................................................... 2163.2.El driver.................................................................................... 2163.3.El prembulo ............................................................................ 2183.4.Funciones del depurador............................................................ 2193.5.Ejemplo de ejecucin................................................................. 225

Referencias

Pg 6

El shell BashMacProgramadores

Tema 1

Introduccin aBash

Sinopsis:

Comosejustificaenelacercade,estetutorialvaaomitirlosaspectosmsbsicosdelshellqueesnormalconocerporpartedecualquierpersonaquehayausadomnimamenteunshellUNIX.

Enesteprimertemavamosarepasarunconjuntodeaspectosfundamentalesque,aunqueenpartepuedeconocerellector,creemosqueconvieneaclararantesdeprofundizar.

Porconsiguiente,recomendamosempezarleyendoesteprimertema,yaquesino pueden quedar ciertos aspectos sin concretar que luego podran hacerfaltaparaseguirmscmodamentelasexplicaciones.

Debidoasusobjetivos,estetemaestescritoavanzandodeformaconside-rablementemsrpidaysuperficialqueenrestodetemas.

Pg 7

El shell BashMacProgramadores

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

Siprefiereusarunaversinmsmodernadeshellquelaquevienepreinstalada con Mac OS X puede bajrsela del proyecto Fink1:

1 Si no tiene Fink instalado puede bajrselo de http://fink.sourceforge.net/

Pg 8

El shell BashMacProgramadores

$ fink list bashInformation about 4975 packages read in 12 seconds.bash3.0-2The GNU Bourne Again Shellbash-completion 20041017-1 Command-line completions ...bash-doc3.0-1Extra 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.

Pg 9

El shell BashMacProgramadores

2. Expansin de nombres de ficheros ydirectorios

2.1.Los comodines

Para referirnos a varios ficheros es muy tpico usar los comodines de la Tabla1.1.Unsitiotpicodondeseusanloscomodineseselcomandols.Estecomandosinargumentoslistatodoslosficherosdeldirectorio,perolepodemos 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.

ComodnDescripcin?Uno y slo un carcter*Cero o ms caracteres[conjunto]Uno los caracteres de conjunto[!conjunto] Un carcter que no este en conjuntoTabla 1.1: Comodines de fichero

Muchasvecesqueremosreferirnosaunconjuntodeficherosparalocualusamos 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.

Otrocomodnmenosusadoes? quesustituyeporunslocarcter,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,peronocesa.AdemspodemosindicarunconjuntodecaracteresASCIIconsecutivos, por ejemplo [a-z] seran todas las letras minsculas, [!0-9]

Pg 10

El shell BashMacProgramadores

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 esqueexpandeporun,ysloundgito,porejemploprograma.[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 quesepasaalcomandocp,perosinoexistieraningnficherocuyonombrecumpliese 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

Esdecir,comopodramospensar,alfallarnosepasaunalistavacaalcomando. Piense por un momento lo que ocurrira con algunos comandos sise hubiese diseado as.

Estefuncionamientoesligeramentedistintoaldetcsh,dondesinoseexpandeelcomodnnoseejecutaelcomando,enBashseejecutaelcomando aunque luego ste produzca un error.

2.2.El comodn tilde

El 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), por

ejemplosiusamos~carol/carta.txtnosexpandepor

/Users/carol/carta.txt.

Ademspodemosusarelcomodntildeparareferirnosanuestropropiodirectorio,elcuyocasodebemosdeprecederloporunabarra,p.e.~/carta.txt seexpandeporelnombredemidirectorio,enmicaso/Users/fernando/carta.txt.

Observeladiferenciaentreponerlabarraynoponerla,sinolahubierapuesto(hubierapuesto~carta.txt),mehabraexpandidoporlaruta/Users/carta.txt, y si no existe un usuario con el nombre carta.txthubiera producido un error indicando que no existe el directorio.

Pg 11

El shell BashMacProgramadores

2.3.El comodn llaves

El 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

Enelapartado2.1comentamosqueunproblemaquetenaelcomodncorchete 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.cppclave.h

Sepuedeusar.. parahaceralgosimilaraloquehacenloscorchetesobteniendo 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

Pg 12

El shell BashMacProgramadores

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 extendidos

Bash 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.Estolopodemossolucionarconelcomodnextendido+(pattern-list) de la forma: carta+([0..9]).txt

Pg 13

El shell BashMacProgramadores

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 elcorchetesloaceptabauncarcter.Ahorapodemosusarelcomodn@(pattern-list) paraindicarlalistadeextensionesaaceptar.Porejemplo *.@(c|o|h|cpp) encontrara correctamente estos ficheros:

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

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

Siloquehubiramosqueridoesencontrartodoslosficherosexceptolos.gif,los.jpgylos.htmlpodramoshaberusadoelpatrn!(*.html|*gif|*jpg).Sinembargo,enestecasonopodramoshaberusado *.!(html|gif|jpg)

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

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

Pg 14

El shell BashMacProgramadores

3. Los comandos internos de Bash

Bash busca los comandos a ejecutar en los directorios indicados en la variabledeentorno$PATH,peroademsexistenunaseriedecomandosquenocorresponden 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 printsthelistofaliasesintheformaliasNAME=VALUEonstandard output.Otherwise, an alias is defined for each NAME whose VALUEis given.A trailing space in VALUE causes the next word to becheckedforaliassubstitutionwhenthealiasisexpanded.Alias returns true unless a NAME is given forwhich no alias has been defined.

Pg 15

El shell BashMacProgramadores

4. Redirecciones y pipes

4.1.Operadores de redireccin

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

Cadaprogramavaatenerasociadassiempreunaentradaestndar(pordefecto el teclado), una salida estndar (por defecto la consola), y una salidade errores estndar (por defecto tambin la consola).

Siqueremos,podemoscambiarlaentradaestndarparaqueelprogramarecibadatosdeunficherousandoeloperadorderedireccin ahora

Enva el da y hora actuales al fichero ahora.

Tambinpodemoscambiaralavezlaentradaysalidaestndardeunprograma 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.Pipes

Es 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 haceesrecogerlaentradaestndaryirlamostrandopocoapoco(pginaapgina),luegosiporejemplotenemosundirectorioconmuchosficherospodemos hacer:

$ ls -la | more

y se irn mostrando pgina a pgina los ficheros.

Pg 17

El shell BashMacProgramadores

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 ordenados al-fabticamente.

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.

5. Ejecucin secuencial y concurrente decomandos

Podemosejecutaruncomandoquetardemuchoenejecutarseydejarloejecutando en background precedindolo por &. Por ejemplo para compilar unconjunto de ficheros fuente de un programa C++ podemos hacer:

$ gcc *.cpp &

Aunqueelprocesosesigueejecutandoenbackground,losmensajesqueproducesalenenlaconsolaimpidindonostrabajancmodamente.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.

Otrasvecesloquequeremosesesperaraqueseacabedeejecutaruncomando 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.

Pg 18

El shell BashMacProgramadores

6. Caracteres especiales y entrecomillado

Los caracteres , |, & *, ? , ~, [, ], {, } son ejemplos de caracteresespecialesparaBashqueyahemosvisto.LaTabla1.2muestratodosloscaracteres especiales de Bash.

Msadelanteveremosotroscomandostienensuspropioscaracteresespeciales, como puedan ser los comandos que usan expresiones regulares olos operadores de manejo de cadenas.

CarcterDescripcin~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 escapeRedirigir 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 terminacinTabla 1.2: Caracteres especiales de Bash

6.1.Entrecomillado

Aunque 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).

Porejemplosiqueremosescribirenconsolaelmensaje:2*3>5 es unaexpresin cierta, podemos usar el comando echo as:

Pg 19

El shell BashMacProgramadores

$ 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.

Sinembargo si entrecomillamos usando ', el carcterde entrecomilladofuerte obtenemos el resultado esperado:

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

Unejemplomsprcticodelentrecomilladoeselcomandofind quenospermite 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 denuestrodirectorioactualeneldiscoduro.Paraevitarloesrecomendableentrecomillarlo:

$ find / -name '*.c'

En la Tabla 1.2 aparece el entrecomillado dbil ", el cual pasa slo poralgunosdelospasosdelshell,odichoconotraspalabras,interpretasloalgunoscaracteresespeciales.Msadelanteveremoscuandoespreferibleusarestetipodeentrecomillado,demomentousaremossloelentrecomillado fuerte.

6.2.Caracteres de escape

Otra 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

Pg 20

El shell BashMacProgramadores

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 deargumentosdelalneadecomandos,siqueremosquenoconsidereelespacio 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

SiqueremosqueBashnointerpreteelcarcterdeescapepodemosentrecomillarlo '\', o bien hacer que l se preceda a si mismo \\.

6.3.Entrecomillar los entrecomillados

Podemosusarelcarcterdeescapeparaquenoseinterpretenlosentrecomillados 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 lneas

Otro problema es como escribir un comando que ocupa varias lneas. Bashnos permite utilizar el carcter de escape para ignorar los cambios de lnea dela 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 Bashnospidequesigamosescribiendosinnecesidaddeponeruncarcterdeescape a los cambios de lnea:

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

Pg 21

El shell BashMacProgramadores

> 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.

Ladiferenciaestenqueenelprimercasoloscambiosdelneasoneliminados, y en el segundo caso no.

Si este documento le est resultando til puede plantearse el ayudarnos amejorarlo:Anotando los errores editoriales y problemas que encuentre y envindlosal sistema de Bug Report de Mac Programadores.Realizando una donacin a travs de la web de Mac Programadores.

Pg 22

El shell BashMacProgramadores

Tema 2

Combinacionesde teclas

Sinopsis:

Nadaesmstilalahorademanejardeformafrecuenteunprogramaquesabermanejarunbuenconjuntodecombinacionesdeteclasquenosayudenarealizaroperacionesfrecuentesrpidamente.

EnelcasodeBashesfcilidentificarcuandounusuarioconoceestascombi-nacionesdeteclas:Nossorprendeverconquevelocidadescribeensuconso-la.

Enestetemacomentaremoslascombinacionesdeteclasmstiles.Lereco-mendamosqueintenterecordarlasyquevuelvaaconsultarestetemacuan-tasveceshagafaltahastaquelasutilicedeformamecnica,vercomoau-mentasuproductividad.

Pg 23

El shell BashMacProgramadores

1.El historial de comandos

Bash mantiene un histrico de comandos el cual lee al arrancar del ficherosituadoeneldirectoriohome.bash_history,durantesuejecucinvaalmacenando en memoria los comandos ejecutados, y al acabar la sesin losescribe al final del fichero .bash_history.

EnprincipiopodemosmodificarelficheroqueusaBashparaguardarelhistricoindicndoloenlavariabledeentornoBASH_HISTORY.Aunqueraramente ser til hacer esto.

Puede usar el comando history para obtener un listado de su historial. Parabuscar un comando usado recientemente puede usar:

$ history | grep "algo"

La forma ms cmoda de referirse a comandos previamente utilizados es usarlasteclasdelcursorflechaarribayflechaabajo.Siannolasconocaprubelas.

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 slolosltimoscomandosdelhistorialynotodos.Paraeditarunodeellosindicamos su nmero a fc:

$ fc 42

Pg 24

El shell BashMacProgramadores

fc abreelcomandoeneleditorquetengamospredefinidoenlavariableEDITOR y nos permite editarlo.

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 anteriores

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

ComandoDescripcin!!Ejecutar el ltimo comando!nEjecutar el comando nmero n!cadenaEjecutar el ltimo comando que empiece por cadenaTabla 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.Tengaseencuentaqueejecutaelcomandomsrecientequeempiece por cadena.

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

Pg 25

El shell BashMacProgramadores

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:-istripicrnl-inlcr-igncrixon-ixoffixanyimaxbel -ignbrk brkint -inpck -ignpar -parmrkoflags: opost onlcr -oxtabs -onocr -onlretcflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb-crtscts -dsrflow -dtrflow -mdmbufdiscard dsuspeofeoleol2eraseintr^O^Y^D ^?^Ckilllnext minquitreprint startstatus^U^V1^\^R^Qstopsusptimewerase^S^Z0^W

Elcomando,apartededarnosciertosflagssobredistintosaspectosdelcomportamiento del terminal, nos muestra las combinaciones de teclas quetenemos asignadas a las tareas ms frecuentes (recurdese que ^X significaCtrl+X).Algunasdeestascombinacionesdeteclasestnobsoletas,ynomerecemucholapenarecordarlas,perootras,lasquesemuestranenlaTabla 2.2, si que son muy tiles:

Combinacinde tecla Nombrestty Descripcin

Ctrl+CintrPara el comando actualCtrl+\quitFuerzalaparadadelcomandoactual(usarsiCtrl+C no responde)Ctrl+DeofFinal del flujo de entradaCtrl+UkillBorradesdelaposicinactualalprincipiodelalneaCtrl+WweraseBorradesdelaposicinactualalprincipiodelapalabraTabla 2.2: Teclas de control del terminal

Para detener un comando es muy tpico usar la combinacin de teclas Ctrl+C,stamandaunmensajealprogramaparaquepuedaterminarliberandocorrectamente los recursos asignados. Si este programa por alguna razn no

Pg 26

El shell BashMacProgramadores

termina(ignoraelmensajequeleenvaCtrl+C)siemprepodemosusarCtrl+\, 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.

3.Modos de edicin en la lnea de comandos

Por qu no puedo editar mis comandos Bash de la misma forma que editotextoenuneditordetexto?EstaesunaideaintroducidaporBash.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 sepuedenusartambinenBash,sinoconoceemacslerecomendamosqueaprendaausarlo,porquees,yserdurantemuchosaos,unclsicodelmundo 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 lnea

Algo 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, pero

Pg 27

El shell BashMacProgramadores

desde que los teclados tienen cursores estas teclas han perdido su utilidadreal. Estas teclas se resumen en la Tabla 2.3.

Combinacinde teclas Descripcin

Ctrl+AIr al principio de la lneaCtrl+EIr al final de la lneaEsc+BIr una palabra hacia atrs (backward)Esc+FIr una palabra hacia adelante (forward)Ctrl+BIr una letra hacia atrsCtrl+FIr una letra hacia adelanteTabla 2.3: Combinaciones de teclas para moverse por la lneaOtra opcin muy til, pero exclusiva del terminal de Mac OS X, es pulsar en laposicin de la lnea a la que quiere moverse con la tecla Opcion pulsada.

3.2.Borrar partes de la lnea

Otra 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.

Enelapartado2yavimosquecombinacionesdeteclaproporcionabaelterminal,yvimosqueconCtrl+Upodamosborrardesdelaposicindelcursor 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 elprincipiodelapalabradondeestemossituados,vimosquepodamosusarCtrl+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.

LaltimaoperacindeborradosepuededeshacersiempreconlateclaCtrl+Y.

Combinacinde teclas Descripcin

Ctrl+UBorra de la posicin actual al principio de la lneaCtrl+KBorra de la posicin actual al final de la lneaCtrl+WBorra de la posicin actual al principio de la palabraEsc+DBorra de la posicin actual al final de la palabraCtrl+DBorra el carcter actual hacia adelanteCtrl+YDeshace el ltimo borrado (Yank)Tabla 2.4: Combinaciones de teclas para borrar

Pg 28

El shell BashMacProgramadores

3.3.Buscar en el historial

Yacomentamosquelasteclasdelcursornospermitanmovernosporelhistrico 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 deteclaselpromptcambiadeforma,ysegnvamosescribiendonosvaindicando el comando del histrico que cumple el patrn dado:

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

Si pulsamos intro se ejecutar el comando actualmente encontrado. Si porcontra pulsamos Esc pasaremos a poder editar el comando encontrado. PorltimosipulsamosCtrl+Gseabortarlabsquedaylalneadeedicinquedar limpia. Estas combinaciones de teclas se resumen en la Tabla 2.5.

Combinacinde teclas Descripcin

Ctrl+RRealiza una bsqueda hacia atrs (Reverse)IntroEjecuta el comando encontradoEscPasa a editar el comando encontradoCtrl+GCancela la bsqueda y deja limpia la lnea de edicinTabla 2.5: Combinaciones de teclas para bsquedas

3.4.Autocompletar con el tabulador

Una 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 texto es-crito, Bash completa la palabra.

3.Si hay un directorio que comienza por el nombre escrito, Bash comple-taelnombrededirectorioseguidoporunabarradeseparacindenombres de directorios /.

Pg 29

El shell BashMacProgramadores

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 pudo termi-nar de completar.

5.Cuando Bash no puede completar una cadena (por haber varias posi-bles que empiezan igual), podemos pulsar dos veces el tabulador y senos mostrar una lista con las posibles cadenas candidatas.

4.La librera readline

LalibrerareadlineesunalibreraGNUquepermiteeditarlneasdetextousando los modos de emacs y vi. Aunque originariamente creada por Bash,actualmente la utilizan multitud de comandos GNU. Esto permite estandarizarlas combinaciones de teclas entre muchos comandos.

readlinesepuedepersonalizarusandoficherosdeconfiguracinobienasignandocombinacionesdeteclasparalasesin.Enlossiguientessubapartados estudiaremos cada una de estas formas de configurarla.

4.1.El fichero de configuracin

readline tiene un fichero de configuracin global que debe ser colocado en/etc/inputrc,yotroparacadausuarioquepordefectosellama.inputrc yquesedebecolocareneldirectoriohomedecadausuario.Podemos cambiar este fichero usando la variable de entorno INPUTRC paraindicar una ubicacin distinta.

CuandoBasharrancaleeestosficheros(siexisten)ycargasusvalores.Dentrodelficheropuedehabercomentarios(precedidospor#),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 asignacionesdecombinacionesdeteclasafuncionesdereadline.Readlinetieneunconjuntograndedefuncionesquepodemosencontrardocumentadaseninfo readline oenman bash.Estasfuncionesrealizanmultituddeoperacionescomunes.Paralistarestasvariablespodemoscrearelfichero.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

Pg 30

El shell BashMacProgramadores

Comoelfichero.inputrc noseleehastalogarnosdenuevoenBashpodemosusarlacombinacindeteclasCtrl+XCtrl+Rparaquereadlinevuelva 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.

SecuenciaDescripcin\C-Tecla Ctrl\M-Tecla de escape (Meta)\eSecuencia de escape\\El carcter \ literal\"El carcter " literal\'El carcter ' literalTabla 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-, yporltimosiqueremosreferirnosateclasespecialespodemosusarsecuencias de escape que se representan con \e.

Porejemplo,vimosqueparaborrarunalneadelaposicindelcursoralprincipio 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() dereadline,modificandoelficherodeconfiguracindereadline como se muestra ms abajo. Otro problema que tiene el terminal esquenormalmentelateclasDELnofuncionacorrectamente,enestecasonecesitamos 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 conlasfuncionesdereadline(yquetambinpuedeconsultarusandoCtrl+XCtrl+V del ejemplo del apartado anterior), a las cuales podemos asignar un

Pg 31

El shell BashMacProgramadores

valor 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:$ cd Music/

Paraellopodemosaadirlasiguientelneaalficherodeconfiguracindereadline:

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

4.2.Asignacin de teclas de sesin

Siloquequeremosesprobarcombinacionesdeteclasquenoqueremosalmacenardeformapermanentepodemosusarelcomandobind,cuyasintaxisessimilaraladelficherodeconfiguracin,perotenemosqueencerrar 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 teclasaotraqueyaexiste.Porejemplo,enelapartadoanteriorparasacarlasfunciones de readline creamos la combinacin de teclas Ctrl+X Ctrl+F, pero alusarestecomandodescubrimosqueyaexistalacombinacinCtrl+Gquehace 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

Pg 32

El shell BashMacProgramadores

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 posterior edi-cin:

$ bind -p > .inputrc

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

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

Ejecutar ls -la al pulsar Ctrl+L.

Pg 33

El shell BashMacProgramadores

Tema 3

Personalizar elentorno

Sinopsis:

EnestetemaveremoscomohacerelentornomsagradablepersonalizandodistintosaspectosdeBash.

Empezaremos viendo los ficheros que configuran Bash siempre que nos lo-gamos. Tambin veremos como personalizar distintos aspectos del compor-tamientodeBash,yquevariablesdeentornosparticipanenestapersonaliza-cin.

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

Pg 34

El shell BashMacProgramadores

1.Los ficheros de configuracin de Bash

Cada vez que nos logamos en la cuenta se ejecuta el contenido del fichero/etc/profile,yluegosemiraaversieneldirectoriohomeexisteelfichero .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 cambiosenesteficheroyqueremosverlossinsalirdelacuentapodemosusarelcomando 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 haber ejecutado as:

$ . .bash_profile

Bashpermiteusardosnombresalternativospara.bash_profile porrazonesdecompatibilidadhistrica:.bash_login,nombrederivadodelfichero .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,slosistetampocoexiste,compruebasiexiste.profile.Laraznporlaqueseeligiesteordendebsquedaesquepodemosalmacenaren.profile opcionespropiasdelBourneShell,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 seejecutasloallogarnos,siabrimosotroshell(ejecutandobash osu)desdelalneadecomandosdeBashloqueseintenta 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, contieneordenesqueseejecutarnalabandonarlacuenta,porejemploeliminarficheros temporales o almacenar datos de actividad de usuarios en un ficherode log.

Pg 35

El shell BashMacProgramadores

2.Los alias

Unaliasesunnombremscortoparauncomandoqueusamosmuyamenudo.

Unejemploclsicodealiasquesesueleencontrarmuchasvecesen/etc/profile es:

$ alias ll='ls -laF'

Ahora podemos usar el alias ll para hacer un listado detallado del directorio.Otros dos alias bastante tiles son:

$ alias ..="cd .."$ alias ...="cd .. ; cd .."

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 delaasignacindelaliasacabaconunespacio,entoncesBashintentahacersustitucindealiasenlasiguientepalabradelcomando.Porejemplosihacemos:

$ alias cat='cat '$ cat ASCII

Obtendremos la tabla ASCII en pantalla.

Si usamos el comando alias sin parmetros, obtenemos un listado de todoslosaliasdefinidos.Siqueremosconocerelvalordeundeterminadoaliaspodemos usar el comando alias seguido del nombre del alias sin smbolo =ni valor.

$ alias llalias ll='ls -laF'

Pg 36

El shell BashMacProgramadores

Porltimo,siqueremosborrarladefinicindeunaliaspodemosusarelcomando unalias:

$ unalias ll

3.Las opciones de Bash

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

Parafijarestasopcionesusamoselcomandoshopt (shelloption).Siejecutamos este comando sin argumentos obtendremos un listado de todaslas opciones del shell y su valor actual.

Todasestasvariablessonbooleanasytienenvalordeon/off.Podemosactivar estas opciones con shopt -s opcion y desactivarlas con shopt -u opcion.

LaTabla3.1muestralasprincipalesopcionesdeshopt juntoconunadescripcin de su propsito.

OpcinDescripcincdable_varsPermite que cd use los valores de las variablescomo nombres de directorios.cdspellIgnora pequeos errores en los cambios dedirectorio con cd. Slo en la ejecucininteractiva.cmdhistGuarda los comandos que hemos escrito envarias lneas en una sola lnea del historial.dotglobIncluye en la expansin de comodines losficheros que empiezan por punto (.).expand_aliasesExpande un alias cuando lo ejecuta.extglobUtiliza extensiones de los comodines. Vaseapartado 2.4 del Tema 1. El trmino "glob"tambin se usa a veces para referirse a loscomodines.failglobSi falla la expansin de un comodn porque noencuentra nada falla el comando (como hace elC Shell).force_fignoreLos sufijos especificados en la variable deentorno FIGNORE no se usan para completarpalabras con tabulador.hostcompleteSe 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 #)

Pg 37

El shell BashMacProgramadores

login_shellVariable de slo lectura que indica si Bash hasido lanzado como un shell de loginnocaseglobIndica si los comodines expanden sinsensibilidad a maysculas/minsculas. Noconfundir con la variable completion-ignore-case de inputrc que lo que hacaera expandir con tabulador.nullglobHace que cuando un patrn no encuentraficheros, se expandan por la cadena vaca en vezde por el patrn sin expandir.sourcepathHace que el comando interno source busque elargumento en los directorios que indique PATHTabla 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. Porejemplositenemoseldirectorio/usr/local/mldonkey/incomming alquesolemosirmuyamenudodesdelaconsolapodemosdefinirenlosficheros 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 $.

Otraopcinmuytilescdspell quepermitequeseignorenpequeoserrores 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.

Pg 38

El shell BashMacProgramadores

4.Las variables de entorno

Las variables de entorno nos ayudan a configurar el entorno en el que se eje-cutan los programas.

Para declararlas es importante recordar que las variables de entorno no pue-den tener espacios, y si queremos asignar un valor con espacio debemos deentrecomillarlo, 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 entrecomillado

En el apartado 6.1 del Tema 1 comentamos que las comillas dobles (las dbi-les) interpretaban algunos de los caracteres que contenan. Uno de ellos es elcarcter $, el cual nos permite expandir el valor de una variable dentro deuna 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 prompt

PodemospersonalizarelpromptdeBashusandolasvariablesdeentornoPS1, PS2, PS3 y PS4. La Tabla 3.2 muestra las opciones de personalizacinque podemos usar en cualquiera de los prompt.

Pg 39

El shell BashMacProgramadores

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 la m-quina, para lo cual se usa la opcin \$ que muestra una # si somos root, o un$ en cualquier otro caso.

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

Muchas veces el prompt nos ayuda a saber en que mquina estamos situa-dos, esto es til por ejemplo cuando tenemos la costumbre de hacer muchostelnet o ssh a otras mquinas. En este caso podemos usar la opcin \H quenos da el nombre de la mquina donde estamos situados, o la opcin \h quenos 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 el ter-minal virtual.

Pg 40

El shell BashMacProgramadores

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.

OpcinDescripcin\aEl carcter ASCII bell (007)\ALa hora en formato HH:MM\dLa fecha en formato semana mes dia\D {formato} Nos permite personalizar ms la fecha\eEl carcter de escape ASCII (033)\HHostname\hEl nombre de la mquina hasta el primer punto\jNmero de jobs hijos del shell\lNombredelterminalenelqueestamostrabajando(p.e.ttyp2)\nRetorno de carro y cambio de lnea\rRetorno de carro\sNombre del shell\tHora en formato HH:MM:SS con 12 horas\THora en el formato anterior pero con 24 horas\uNombre de usuario\vVersin de Bash\wRuta del directorio actual\WNombre del directorio actual (sin ruta)\#Nmero de comandos ejecutados\!Nmero histrico del comando\$# si somos root, o $ en caso contrario\nnnCdigo de carcter a mostrar en octal\\La barra haca atrs\[Empieza una secuencia de caracteres no imprimibles, comolos caracteres de control de secuencias del terminal\]Acaba una secuencia de caracteres no imprimiblesTabla 3.2: Opciones de personalizacin del prompt

PS2 es el prompt secundario y por defecto vale >. Se usa cuando usamos elmodo de entrada multilnea, en el que entramos al escribir un comandoinacabado, 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.

Pg 41

El shell BashMacProgramadores

Por ltimo, PS3 y PS4 son prompts de programacin y depuracin que estu-diaremos en temas posteriores.

4.3.Variables de entorno internas

Existen 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.

VariableDescripcinSHELLPath del fichero que estamos usandoLINESLneas del terminal en caracteresCOLUMNSColumnas del terminal en caracteresHOMEDirectorio home del usuarioPWDDirectorio actualOLDPWDAnterior directorio actualUSERNombre de usuario en la cuenta donde estamos logadosTabla 3.3: Variables de entorno internas

Algunasvariablesseactualizandinmicamente,porejemploLINES 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 variables

Las variables de entorno que definimos dentro de una sesin de Bash no es-tndisponiblesparalossubprocesosquelanzaBash(slolaspuedeusarBash 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 la asigna-mos 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 sin argumen-tos.

Pg 42

El shell BashMacProgramadores

Tema 4

Programacinbsica del shell

Sinopsis:

EstetemaintroducelosconceptosmsbsicosdelaprogramacindescriptsyfuncionesconBash.

Enestemomentodeberadesercapazdemanejarseconelterminal(elmodointeractivo)conmssolturaqueantesdeleerestetutorial.Ahorapretende-mosempezaraentenderlosscriptsqueconfiguransumquina,yaqueseacapazdecrearsuspropiosscripts.

Eltemasuponequeellectorconocelosconceptosbsicosdeprogramacinenalgnlenguajeestructurado(C,Pascal,Basic).Bashnousalosconceptosdeprogramacinorientadaaobjetos,perosiconoceestetipodeprograma-cin(p.e.Java)tambinleserviraqu,yaquelaprogramacinestructuradaesunsubconjuntodelaorientadaaobjetos.

Bashesunlenguajemuycrptico,conloqueserarecomendablequesefijarabienenlasintaxis,yqueintentarahacerlosejerciciosqueproponemosensuordenadorconelfindeconsolidadlasideasbsicasquevamosadesarrollarenestetema.

Pg 43

El shell BashMacProgramadores

1.Scripts y funciones

1.1.Scripts

UnscriptesunficheroquecontienecomandosBashejecutables.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.

Lasegundaformaimplicaponeralficheropermisodeejecucin(conelcomandochmod +x fichero).Unavezpuestoestepermiso,podremosejecutarlosiemprequeestenalgunodelosdirectoriosindicadosenlavariable de entorno PATH. De hecho muchos comandos comunes (p.e. spelloman)estnimplementadoscomoscriptsBash,ynocomoprogramasCejecutables.Esmuytpicoenestecasoempezarelscriptponiendoenlaprimera 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. Otrosscriptsparaotroslenguajescomoawk,ksh operl tambinseescribenempezando 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 enunprocesoaparte,exceptoconloscomandosinternosqueseejecutandentrodelprocesodelscript,locualleshacemsrpidosylespermiteacceder a las variables de entorno no exportadas.

1.2.Funciones

Las 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

Pg 44

El shell BashMacProgramadores

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}

Noexistediferenciaentreellos,yusaremosambosindistintamente.Paraborrar una funcin podemos usar el comando unset -f nombrefn.

Cuandodefinimosunafuncinsealmacenacomounavariabledeentorno(con su valor almacenando la implementacin de la funcin). Para ejecutar lafuncinsimplementeescribimossunombreseguidodeargumentos,comocuando ejecutamos un comando. Los argumentos actan como parmetrosde la funcin.

Podemosverquefuncionestenemosdefinidasenunasesinusandoelcomandodeclare -f.Elshellimprimelasfunciones,ysudefinicin,ordenadasalfabticamente.Sipreferimosobtenersloelnombredelasfunciones 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 Bash

A 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 enque se dan sus directorios en la variable de entorno PATH.

Pg 45

El shell BashMacProgramadores

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. En poste-riores temas veremos su utilidad.

Si nos interesa conocer la procedencia de un comando podemos usar el co-mando interno type. Si le damos un comando nos indica cual es su fuente, sile 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 tambintieneopcionesquenospermitenobtenerdetallesdeunsmbolo. 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

Podemosconocereltipodeunsmboloconlaopcin-t:Nosdevolveralias, keyword, function, builtin o file. Por ejemplo:

$ type -t cdbuiltin$ type -t cpfile

Pg 46

El shell BashMacProgramadores

2.Variables del shell

Principalmente Bash utiliza variables de tipo cadena de caracteres. Esto le di-ferencia de otros lenguajes de programacin donde las variables tienen distin-tos tipos. Aunque ste es el tipo por defecto de las variables de Bash, msadelante veremos que las variables en Bash tambin pueden tener otros ti-pos, como por ejemplo enteros con los que realizar operaciones aritmticas.

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

2.1.Los parmetros posicinales

Los 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 x activa-do 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.

Paradefinirunafuncinpodemosescribirlaenunficheroycargarlaenelshell usando el comando source, o bien definirla directamente en modo in-teractivo:

Pg 47

El shell BashMacProgramadores

$ 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

El modo de entrada multilnea (que explicamos en el apartado 4.2 del Tema3) hace que el shell nos vaya pidiendo lneas hasta que cerramos la llave. Du-rante este modo aparecer el prompt secundario (>).

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, es-to es as porque $0 siempre se sustituye por el nombre de script (no el de lafuncin), o -bash si lo ejecutamos directamente desde la lnea de comandos.

Por ltimo comentar que no podemos modificar el valor de las variables posi-cinales, slo se pueden leer, si intentamos asignarlas un valor se produce unerror.

2.2.Variables locales y globales

Por 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"}

DiHolaListado 4.2: Script que llama a una funcin para saludar

Al ejecutarlo obtenemos:

$ saluda FernandoHola

Pg 48

El shell BashMacProgramadores

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 funcin ten-dremos que pasrselo como muestra el Listado 4.3.

# Script que llama a una funcion para saludar

function DiHola {echo "Hola $1"}

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

A diferencia de los parmetros posicinales, el resto de variables que defini-mos 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 la va-riable 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 $dondeListado 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'}

Pg 49

El shell BashMacProgramadores

donde='En el script'echo $dondeEstasAquiecho $dondeListado 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 definir de-ntro de una funcin. Por ejemplo, en el Listado 4.6 se muestra como defini-mos la variable global quiensoy dentro de la funcin EstasAqui() y lausamos 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.

Pg 50

El shell BashMacProgramadores

Tanto $* como $@ nos devuelven los argumentos recibidos por el script ofuncin. Cuando no se entrecomillan se comportan exactamente igual, pero alencerrarlos en comillas dbiles "$*" crea un nico token que corresponde atodos los argumentos recibidos mientras que "$@" crea un token por cadaargumento recibido.

Normalmente $* como $@ se utilizan con el bucle for (que se explica en elapartado 2 del Tema 5). El Listado 4.7 muestra cmo se comporta cada unade estas variaciones con los argumetos recibidos.

for i in $@; do echo "\$@ $i"; donefor i in $*; do echo "\$* $i"; donefor i in "$@"; do echo "\"\$@\" $i"; donefor i in "$*"; do echo "\"\$*\" $i"; doneListado 4.7: Ejemplo de uso de $* y $@

Al ejecutarlo obtenemos:

$ ./recibe hola adios$@ hola$@ adios$* hola$* adios"$@" hola"$@" adios"$*" hola adios

Cuandolosencerramosentrecomillasdbilesexistendosdiferenciasqueconviene resaltar:

La primera es que podemos cambiar el smbolo que usa "$*" para separarlos argumentos indicndolo en la variable de entorno IFS (Internal Field Se-parator), 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:

Pg 51

El shell BashMacProgramadores

function CuentaArgumentos {echo "Recibidos $# argumentos"}

Ahorapodemospasarlosargumentosrecibidosporelscriptalafuncinusando 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 se interpre-ta cada token 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, "$*" tiene el efecto de que se convierte en un slo token, mientrasque con "$@" cada argumento es un token.

En consecuencia obtenemos las siguientes reglas generales:

1.Siempre conviene usar las variables "$*" y "$@" entrecomilladas paraevitar que los argumentos que contengan espacios sean mal interpre-tados.

Pg 52

El shell BashMacProgramadores

2.Si queremos cambiar el delimitador que separa los argumentos (usan-do IFS) debemos utilizar "@*" entrecomillado.3.Si lo que queremos es pasar los argumentos a una funcin debemos deusar "$@" entrecomillado.

2.4.Expansin de variables usando llaves

Realmente 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 apartado ve-remos cuando se producen las ambigedades que nos obligan a usar la forma${variable}.

La forma ${variable} se usa siempre que la variable vaya seguida por unaletra, dgito o guin bajo (_), en caso contrario podemos usar la forma simpli-ficada $variable. Por ejemplo si queremos escribir nuestro nombre (alma-cenado en la variable nombre) y nuestro apellido (almacenado en la variableapellido) 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 parmetro po-sicional.

Pg 53

El shell BashMacProgramadores

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 asignadoCoger 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 sustitucin

La Tabla 4.1 muestra los operadores de sustitucin.

OperadorDescripcin$ {var:-valor}2Si var existe y no es nula retorna su valor,sino retorna valor.$ {var:+valor}1Si var existe y no es nula retorna valor,sino retorna una cadena nula.$ {var:=valor}1Si var existe y no es nula retorna su valor,sino asigna valor a variable y retornasu valor.$ {var:?mensaje}1Si 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 que empie-za en offset y tiene longitud caracte-res. El primer carcter de var empieza enla posicin 0. Si se omite longitud lasubcadena empieza en offset y continuahasta el final de var.Tabla 4.1: Operadores de sustitucin

2Los 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).

Pg 54

El shell BashMacProgramadores

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

$ {var:+valor} porcontraseutilizaparacomprobarqueunavariabletenga 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 est indefini-da. Por ejemplo $ {veces:=1} asigna 1 a veces si sta no tiene valor.

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}.PorejemplosinombrevaleFernandoLopez,${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 clientes45340Jos Carlos Martinez24520Mari Carmen Gutierrez450Luis Garcia Santos44Marcos Vallido Grandes500Carlos de la Fuente Lopez

Escribir un script que imprima los N clientes que ms saldo tengan. El scriptrecibir como primer argumento el fichero de clientes y, opcionalmente comosegundo argumento, el nmero Nde clientes a imprimir. Si no se proporcionaN,por defecto ser 5. Luego la forma del comando podra ser:

mejoresclientes fichero [cuantos]

Para ello podemos usar el comando sort el cual ordena lneas, y despus elcomando head que saca las primeras lneas de la forma:

sort -nr $1 | head -${2:-5}

Pg 55

El shell BashMacProgramadores

La opcin -n dice a sort que ordene numricamente (no alfabticamente) yla opcin -r dice a sort que saque los elementos ordenados de mayor amenor.head recibecomoargumentoelnmerodelneasamostrar,porejemplo head -2 significa coger las primeras 2 lneas.

Este script aunque funciona es un poco crptico, y vamos a hacer unos cam-bios con vistas a mejorar su legibilidad. Por un lado vamos a poner comenta-rios (precedidos por #) al principio del fichero, y vamos a usar variables tem-porales para mejorar la legibilidad del programa. El resultado se muestra enel Listado 4.8.

# Script que saca los mejores clientes# Tiene la forma:#mejoresclientes []

fichero=$1cuantos=$2defecto=5sort -nr $fichero | head -${cuantos:-$defecto}Listado 4.8: Script que lista los mejores clientes

Estos cambios que hemos hecho mejoran la legibilidad del script, pero no sutolerancia a errores, ya que si por ejemplo no pasamos el argumento $1, conel nombre del fichero, se ejecutar el script as:

sort -nr | head -$5

Y sort se quedar esperando a que entren datos por su entrada estndarhasta que el usuario pulse Ctrl+D o Ctrl+C. Esto se debe a que, aunque con-trolamos que el segundo argumento no sea nulo, no controlamos el primero.

En este caso podemos usar el operador de cadena :? para dar un mensajede error cambiando:

fichero=$1

Por:

fichero=${1:?'no suministrado'}

Ahora, si no suministrados el argumento se produce el mensaje:

./mejoresclientes: 1: no suministrado

Podemos mejorar la legibilidad de este mensaje si hacemos:

fichero_clientes=$1

Pg 56

El shell BashMacProgramadores

fichero_clientes=${fichero_clientes:?'no suministrado'}

Ahora si olvidamos proporcionar el argumento vemos el mensaje:

./mejoresclientes: fichero_clientes: no suministrado

Para ver un ejemplo del operador de cadena := podramos cambiar:

cuantos=$2

Por:

cuantos=${2:=5}

Pero esto no funciona porque estamos intentando asignar un valor a un pa-rmetros posicional (que son de slo lectura). Lo que s podemos hacer es:

cuantos=$2sort -nr $fichero_clientes | head -${cuantos:=$defecto}

El Listado 4.9 muestra el resultado de hacer nuestro script ms tolerante aerrores:

# Script que saca los mejores clientes# Tiene la forma#mejoresclientes []

fichero_clientes=$1fichero_clientes=${fichero_clientes:?'no suministrado'}cuantos=$2defecto=5sort -nr $fichero_clientes | head -${cuantos:=$defecto}Listado 4.9: Script que lista los mejores clientes mejorado

3.2.Operadores de bsqueda de patrones

En la Tabla 4.2 se muestran los operadores de bsqueda de patrones existen-tes y una descripcin de su comportamiento.

Un uso frecuente de los operadores de bsqueda de patrones es eliminar par-tes de la ruta de un fichero, como pueda ser el directorio o el nombre del fi-chero. Vamos a exponer algunos ejemplos de cmo funcionan estos operado-res: Supongamos que tenemos la variable ruta cuyo valor es:

ruta=/usr/local/share/qemu/bios.core.bin

Pg 57

El shell BashMacProgramadores

Y ejecutamos los siguientes operadores de bsqueda de patrones, entonceslos resultados seran los siguientes:

OperadorResultado${ruta##/*/}bios.core.bin${ruta#/*/}local/share/qemu/bios.core.binruta/usr/local/share/qemu/bios.core.bin${ruta%.*}/usr/local/share/qemu/bios.core${ruta%%.*}/usr/local/share/qemu/bios

En la bsqueda de patrones se pueden usar tanto los comodines tradic