Sistemas operativos. UNIX

Anuncio
Facultad de Ingenierı́a
Universidad de Buenos Aires
75.08—Sistemas Operativos
UNIX
[email protected]
http://fiuba-7508.50megs.com
Apunte por: Ignacio Errico
[email protected]
Version Preliminar
Marzo de 2003
Índice
1 Introducción.
1.1
1.2
1.3
4
¿Qué es UNIX? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
1.1.1
¿Qué es UNIX entonces? . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
Tareas básicas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
1.2.1
Iniciando el sistema. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
1.2.2
Iniciar una sesión. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
1.2.3
Terminar una sesión. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
1.2.4
Cuentas de usuario y claves de usuario. . . . . . . . . . . . . . . . . . . .
6
1.2.5
Terminales virtuales. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
1.2.6
El comando su. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
1.2.7
Apagando el sistema. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
Conceptos básicos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
1.3.1
Caracteres de control en la lı́nea de comandos. . . . . . . . . . . . . . . .
8
1.3.2
Directorios. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
1.3.3
Permisos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
2 El Shell.
2.1
2.2
2.3
2.4
13
Uso de abreviaturas: Metacaracteres. . . . . . . . . . . . . . . . . . . . . . . . . .
13
2.1.1
Nombres de archivos con metacaracteres. . . . . . . . . . . . . . . . . . .
14
Variables de Ambiente. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
2.2.1
Obteniendo el valor de variables. . . . . . . . . . . . . . . . . . . . . . . .
15
Variable de usuario. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
2.3.1
Sustitución. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
Entrecomillado. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
2
3
2.4.1
2.5
2.6
Tipos de entrecomillado. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
Redireccionamiento de la Entrada y Salida. . . . . . . . . . . . . . . . . . . . . .
18
2.5.1
Ejemplos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
Interconexión. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
3 Programación con el Shell: Shell-Scripting.
21
3.1
Comentarios. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21
3.2
Argumentos y Parámetros. El comando shift. . . . . . . . . . . . . . . . . . . .
21
3.2.1
Parámetros especiales. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
3.2.2
Estado de salida. El comando exit. . . . . . . . . . . . . . . . . . . . . .
23
Pruebas. El comando test. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
3.3.1
Operadores del comando test. . . . . . . . . . . . . . . . . . . . . . . . .
23
3.3.2
Pruebas sobre archivos. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
3.3.3
Prueba de valores para operaciones algebraicas. . . . . . . . . . . . . . . .
24
3.3.4
Prueba de valores para cadena de caracteres. . . . . . . . . . . . . . . . .
24
Aritmética entera. El comando expr. . . . . . . . . . . . . . . . . . . . . . . . . .
24
3.4.1
Operador de longitud. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
Comandos de control. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
3.5.1
Sentencias de Decisión.
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
3.5.2
Sentencias de Iteración. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
28
3.3
3.4
3.5
4 Comandos de Entrada y Salida.
4.1
4.2
4.3
Traducción de caracteres: el comando tr. . . . . . . . . . . . . . . . . . . . . . .
30
4.1.1
Ejemplos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
30
El comando cut. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
31
4.2.1
Ejemplos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
32
El comando paste. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
32
4.3.1
33
Ejemplos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5 Expresiones Regulares.
5.1
5.2
30
34
Expresiones regulares simples. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
35
5.1.1
Algunos ejemplos de expresiones regulares simples. . . . . . . . . . . . . .
35
Expresiones regulares extendidas. . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
5.2.1
36
Ejemplos de REs Extendidas. . . . . . . . . . . . . . . . . . . . . . . . . .
Capı́tulo 1
Introducción.
1.1
¿Qué es UNIX?
El sistema operativo UNIX nació como un sistema de tiempo compartido, orientado a usos
generales. En 1973, Ritchie y Thompson reescribieron el núcleo del sistema (el kernel ) en C,
rompiendo de esta manera la tradición de software de base escrito en assembler. En 1974 se
introduce en las universidades con fines educacionales y poco tiempo después estuvo disponible
con fines comerciales.
UNIX no es en sı́ un sistema operativo, sino un tipo de sistema operativo. Los sistemas operativos
tipo UNIX más conocidos son AIX, SCO, SVR4, SOLARIS.
El éxito de UNIX se debe principalmente a tres causas:
1. Ventaja comercial. Por estar escrito en C es portable, y se puede ejecutar en una gran
variedad de máquinas.
2. Abierto. El código fuente está disponible y escrito en un lenguaje de alto nivel. Esto lo
hace fácil de adaptar a exigencias particulares.
3. De utilidad particular para programadores. Es un sistema operativo rico y productivo para programadores.
Su eficacia se debe al enfoque de la programación, y no a la programación misma: la combinación de distintos comandos simples permiten lograr grandes tareas generales. De esta manera,
monta su potencia en la relación entre los programas, más que en la potencia de los programas
propiamente dichos.
1.1.1
¿Qué es UNIX entonces?
En sentido estricto. Es el núcleo de un sistema operativo de tiempo compartido. Un programa
que controla los recursos de una computadora y los asigna entre los usuarios. Permite a los
4
Sección 1.2. Tareas básicas.
5
usuarios ejecutar sus programas, controla los dispositivos periféricos conectados, y proporciona
un sistema de archivos que permite el almacenamiento a largo plazo de todo tipo de información.
En sentido más amplio. Abarca, además del núcleo, programas esenciales como compiladores,
editores, lenguajes de comandos, programas para copiar e imprimir archivos, y muchas otras
aplicaciones.
1.2
1.2.1
Tareas básicas.
Iniciando el sistema.
Este proceso puede variar levemente respecto de lo que uno está acostumbrado con otros sistemas
operativos. En el caso de no haber instalado otro sistema operativo, el proceso es simplemente
encender la computadora y esperar. Por otro lado, si se está compartiendo el sistema con otro
sistema operativo, es probable que uno tenga que realizar alguna de las siguientes opraciones:
• Seleccionar Linux en el prompt de LILO. Si al instalar el sistema se decidió instalar
LILO (LInux LOader ) la computadora está preparada para iniciar el sistema operativo
que se le especifique ingresando la etiqueta para la partición definida en la instalación.
Presionando la tecla <TAB>, se muestran las etiquetas posibles. Simplemente ingrese la
correspondiente a Linux, o presione <ENTER> si es la partición que LILO debe iniciar por
defecto.
• Iniciar desde un diskette. Si se creó un diskette de booteo al instalar Linux, también
se lo puede usar para iniciar el sistema.
1.2.2
Iniciar una sesión.
Al iniciar el sistema, o al conectarse a una terminal, se visiualiza el siguiente mensaje:
Login:
La primera vez que uno entra al sistema, se debe ingresar el usuario root. Este es el nombre
del usuario que tiene permiso para todo en el sistema. Por lo general se usa para realizar tareas
de administración, como por ejemplo, para crear nuevos usuarios, apagar el sistema, etc.
Dado que este usuario tiene permiso para hacer cualquier cosa, hay que saber que comandos se
ejecutan al entrar como root. Más adelante hablaremos acerca de permisos.
Para ingresar, se debe tipear root y presionar la tecla <ENTER>, y a continuación aparecerá:
Password:
donde se debe tipear la clave del usuario. Tener presente, que si bien no se visualizan los
caracteres cuando uno tipea la clave, se puede corregir con la tecla <BACKSPACE>.
Sección 1.2. Tareas básicas.
6
Recuerde que UNIX es un sistema operativo que distingue mayúsculas de minúsculas
—es “case sensitive”.
Si la clave ingresada es correcta, el sistema mostrará un prompt o sı́mbolo de espera, que a lo
largo de este apunte se representará con el sı́mbolo # (para el caso del root), que es normalmente
el caracter generado por un programa shell o intérprete de comandos, que es la interfaz entre el
sistema operativo y el usuario.
1.2.3
Terminar una sesión.
Si bien existen los comandos logout y exit, es común usar CTRL-D. Esto lleva a la pantalla de
Login: que se describió antes.
1.2.4
Cuentas de usuario y claves de usuario.
Como sugerimos antes, no es una buena idea usar la cuenta de root todo el tiempo. Tarde o
temprano uno comete un error, y con este usuario no hay restricciones que salven.
Vamos a describir la forma más básica de crear un usuario. En el prompt tipeamos:
# useradd igna
# passwd igna
New UNIX password:
Retype new UNIX password:
passwd:
all authentication tokens updated successfully
El comando passwd en general se puede usar para:
• Definir claves para nuevos usuarios.
• Cambiar claves de usuarios existentes.
• Cambiar la clave del usuario loggeado.
El comando requiere que la clave se ingrese dos veces para verificar que no hubieron errores de
tipeo.
1.2.5
Terminales virtuales.
Una herramienta muy útil son las terminales virtuales: se pueden iniciar distintas sesiones
simultáneamente, presionando ALT-Fn.
Habiendo creado el nuevo usuario igna, uno puede presionar ALT-F2 y loggearse con este nuevo
usuario. Para volver a la terminal del root, se presiona ALT-F1.
Sección 1.3. Conceptos básicos.
1.2.6
7
El comando su.
Hay ocasiones en las cuales uno quiere ejecutar algunos comandos como un usuario distinto del
que uno estĺoggeado. Esto es muy útil particularmente para administradores del sistema, que
usan sus cuentas sin privilegios por lo general. Para evitar todo el proceso de loggeo se usa el
comando su, que hace que la sesión de un usuario ordinario se transforme en una sesión de root.
Al ejecutar el comando, pide que se ingrese la clave del root.
Este comando resulta muy útil particularmente si uno es su propio administrador de sistema,
como sucede con muchos usuarios Linux.
1.2.7
Apagando el sistema.
Apagar el sistema no se trata simplemente de apagar la computadora. Aunque uno no esté
ejecutando ningún programa, esto no significa que no hay nada corriendo.
Lo que hay que hacer es ejecutar el comando shutdown, el cual solo puede ser ejecutado por el
root. Esta es una buena oportunidad para usar el comando su.
El formato general de shutdown es:
shutdown <opciones> <tiempo>
El parámetro <opciones> puede ser:
• -h: detener el sistema cuando se terminó de cerrar.
• -r: reiniciar el sistema.
El segundo parámetro, <tiempo>, normalmente es now, aunque también puede ser el valor de
minutos a esperar antes de que se inicie el proceso de cerrado del sistema.
Ejemplos:
shutdown -r +15
Empezar a apagar el sistema dentro de 15 minutos y una vez terminado, reiniciar.
shutdown -h now
Apagar el sistema inmediatamente, y detenerse cuando se termine el proceso.
1.3
Conceptos básicos.
En primer lugar, y como mencionamos antes, UNIX es case sensitive: se distinguen mayúsculas
de minúsculas.
Por otro lado, UNIX es full duplex : los caracteres que se tipean, se envı́an al sistema, el cual
los pasa a la terminal. Este proceso, conocido como eco, los copia directamente a la pantalla,
aunque en ciertas ocasiones se desactiva (por ejemplo, para tipeo de claves).
Los caracteres pueden clasificarse en dos grupos:
Sección 1.3. Conceptos básicos.
8
• Caracteres comunes.
• Caracteres de control.
Los caracteres tipeados son examinados e interpretados antes de llegar a su destino. Todos
los caracteres se transmiten a la terminal, excepto que el echo esté apagado. Los caracteres
se almacenan en el núcleo hasta que se presiona <ENTER>. Cuando un caracter es precedido
por el caracter \ (barra invertida), descarta este caracter y almacena el siguiente caracter como
uno común sin otra interpretación. Al presionar <ENTER>, los datos almacenados se enviarán al
programa que esté leyendo datos de la terminal. Los caracteres serán leı́dos aunque el núcleo
esté ocupado con otras tareas.
Para obtener ayuda acerca de algún comando, usar el comando:
man <nombre-del-comando>
que despliega la manual page para ese comando. Lo primero que se recomienda hacer es ejecutar
man man
es decir, ver la manual page del mismo man. Para volver al prompt mientras se visualiza una
manual page presionar <q>.
Finalmente, en la filosofı́a UNIX, solo existen archivos (una secuencia de bytes) y procesos
(programas en ejecución). Ambos se organizan en estructuras jerárquicas. De esta manera, para
el sistema, el teclado, la diskettera, etc. son archivos.
1.3.1
Caracteres de control en la lı́nea de comandos.
Vamos a comentar algunos caracteres de control útiles al tipear en la lı́nea de comandos. Solo
mencionamos los más útiles, aunque la lista completa se puede ver de [3].
<CTRL-A>
Va al comienzo del texto.
<CTRL-E>
Va al final del texto.
<CTRL-B>
Mueve el cursor un caracter a la izquierda.
<CTRL-F>
Mueve el cursor un caracter a la derecha.
<ALTL-B>
Va al comienzo de la palabra anterior.
<ALTL-F>
Va al comienzo de la palabra siguiente.
Sección 1.3. Conceptos básicos.
9
<CTRL-L>
Limpia la pantalla.
<ALTL-U>
Pone toda la palabra en mayúscula.
<ALTL-L>
Pone toda la palabra en minúscula.
<CTRL-K>
Borra hasta el final de la lı́nea.
<TAB>
Completa la cadena incompleta. Es un caracter muy útil particularmente para trabajar rápidamente
con nombres de archivos largos.
También es útil el manejo de la salida por pantalla:
<CTRL-C>
Interrumpe la ejecución de un programa.
<CTRL-S>
Pausa una salida.
<CTRL-Q>
Continua mostrando una salida pausada.
1.3.2
Directorios.
Los directorios son un tipo de archivo que permiten agrupar jerárquicamente archivos. Permiten
mantener unida información relacionada.
Cada usuario tendrá un home directory, o directorio de login, donde podrá mantener sus archivos.
Al iniciar una sesión se posiciona al usuario en este directorio.
A diferencia del home directory, hablaremos del working directory para referirnos al directorio
en el cual se está posicionado.
Mientras que el working directory cambia al cambiar de directorio, el home directory se mantiene
invariable para un usuario del sistema.
Los directorios privados de los usuarios del sistema suelen estar en /users o /home.
Comandos para administrar directorios.
Describiremos los comandos básicos.
cd <nombre-de-directorio>
Hace que el working directory sea el directorio especificado.
Sección 1.3. Conceptos básicos.
10
mkdir <nombre-de-directorio>
Crea un directorio.
rmdir <nombre-de-directorio>
Elimina un directorio que no contiene archivos.
pwd
Print Working Directory. Imprime la ruta del directorio en el cual se está posicionado.
echo $HOME
Imprime en contenido de la variable de ambiente $HOME, que contiene la ruta del home directory.
Más adelante hablaremos de variables de ambiente.
Jerarquı́a de directorios.
El directorio de máximo nivel es el / (llamado root —¡nada que ver con el usuario root!).
Allı́ se encuentran una serie de directorios, que describiremos a continuación:
/bin
Acá se encuentran los programas básicos.
/dev
Acá se encuentran los dispositivos (terminales, impresoras, etc.). Hablaremos de dispositivos
más adelante.
/etc
Contiene archivos y programas de administración. Solo por mencionar algunos: passwd es un
archivo que contiene datos de los usuarios, rc se ejecuta al iniciar el sistema.
/lib
Biblioteca. Contiene principalemente partes del compilador C, preprocesador de C y, por ejemplo, libc.a que es la biblioteca de subrutinas de C.
/tmp
Temporales. Contiene archivos de vida corta. Por ejemplo, cuando se edita un programa, se
crea en este directorio un archivo de trabajo, que es una copia del original. Este directorio se
depura periódicamente.
/usr
Sistema de archivos de usuario. Contiene esencialmente los directorios descriptos hasta ahora,
con los mismos significados, pero con programas menos vitales para el funcionamiento del sistema. Por ejemplo, el compilador FORTRAN está en /usr/lib.
Vale la pena invertir un tiempo en recorrer estos directorios para estar más familiarizado con el
sistema.
Sección 1.3. Conceptos básicos.
1.3.3
11
Permisos.
Cada archivo tiene un conjunto de permisos asociados, que determinan que se puede hacer y
quien puede hacerlo.
Cuando un usuario ingresa al sistema, éste lo reconoce por un número llamado user id (o
identificador de usuario). Diferentes nombres de usuario pueden tener el mismo user id —
aunque no es algo muy deseable, desde el punto de vista de la seguridad. Además de este valor,
se le asigna al usuario un group id, que lo coloca dentro de una cierta clase de usuarios. El
sistema usa estos dos valores para determinar los permisos para un usuario en relación con un
archivo.
Los permisos de un archivo pueden permitir:
• leer,
• escribir, y/o
• ejecutar
el archivo.
Estas acciones se representan por r, w, x, respectivamente (debido a read, write, execute), y cada
una se asigna a:
• el usuario mismo,
• el grupo al que pertenece el usuario, y
• al resto de los usarios.
Esta clasificación se representa por u, g, o, respectivamente (debido a user, group, others).
Por ejemplo, supongamos que el archivo arch tiene los siguiente permisos: rwx rw- r--. Esto
significa que el usuario puede leer, escribir (modificar) y ejecutar el archivo; que los usuarios
del grupo al que pertenece pueden solo leerlo y modificarlo; y que el resto de los usuarios solo
pueden leerlo.
Para ver los permisos de un archivo, usar el comando:
ls -l [<nombre-del-archivo>]
Los corchetes indican que el parámetro no es necesario. Hablaremos más acerca de este comando
más adelante.
Cambiando los permisos de un archivo.
El comando chmod (change mode), permite cambiar permisos de archivos, con el siguiente formato:
Sección 1.3. Conceptos básicos.
12
chmod <permisos> <archivos>
Solo el dueño de un archivo puede cambiar los permisos de un archivo.
El parámetro <permisos> puede darse de varias maneras. Esencialmente hay dos:
• Con sı́mbolos representativos. Usando las seis letras definidas antes, y usando + o para indicar si se dá el permiso, o si se quita, respectivamente.
Por ejemplo:
chmod u+x arch
Le da permiso de ejecución del archivo arch al usuario.
chmod ug+w-r arch
Les da permiso de modificación al usuario y al grupo del archivo arch, pero les quita
simultáneamente permiso de lectura.
• Con números octales. Para cada clasificación se puede asignar una combinación de tres
permisos, resultando en 23 = 8 alternativas distintas, lo cual sugiere una representación
en base octal para los permisos.
El “bit” de lectura (r) se define como el bit más significativo. Ası́, los permisos rw- se
representan por el número octal 4 + 2 + 0 = 6.
Por ejemplo:
chmod 640 arch
Le asigna los permisos rw- r-- --- al archivo arch, es decir, lectura y modificación para
el usuario, lectura para el grupo al que pertenece el usuario, y ningún permiso al resto de
los usuarios.
El parámetro archivos puede ser uno o varios archivos separados por espacio o con wildcards—
que explicaremos más adelante.
Tener presente que el usuario root tiene permiso para todo.
Capı́tulo 2
El Shell.
Como ya se mencionó antes, cuando un usuario se conecta al sistema, éste presenta un prompt
donde se tipean los comandos que el sistema pasa a ejecutar. No es el kernel el que dirige al
usuario, sino un intérprete de comandos o shell, que es un programa que realiza la interpretación
de los caracteres ingresados.
A continuación hablaremos de las ventajas que presta este intérprete entre el sistema operativo
y el usuario.
2.1
Uso de abreviaturas: Metacaracteres.
Es posible referirse a una serie de archivos mediante el uso de metacaracteres, los cuales son
interpretados por el shell antes de ser pasados al comando en cuestión.
Los siguientes son metacaracteres:
?
Un caracter cualquiera.
*
Cualquier cadena de caracteres.
[conjunto]
Cualquier caracter del conjunto.
[!conjunto]
Cualquier caracter que no este en el conjunto.
Ejemplos.
Supongamos que creamos los directorios Mayo2001, Junio2001, . . . , Mayo2002.
Si que quieren eliminar todos los directorios del año 2001:
13
Sección 2.1. Uso de abreviaturas: Metacaracteres.
14
rmdir *2001
En este caso, el shell sustituye el metacaracter * por Mayo, Junio, etc., y es ésto lo que le pasa
al comando rmdir. Es decir, desde el punto de vista del comando rmdir, es como que el usuario
hubiese tipeado rmdir Mayo2001 Junio 2001 etc., con todos los direcctorios que correspondan.
Si se quieren eliminar los meses Junio y Julio:
rmdir Ju?io*
El shell reemplaza el metacaracter ? por n y l respectivamente, y el * por 2001, que son
las cadenas que corresponden a los archivos del directorio actual, y es ésto lo que le pasa al
comando. Nuevamente, desde el punto de vista del comando rmdir, es como si no se hubieran
usado metacaracteres, porque él no los vé.
Notar que el uso de metacaracteres simplifica el diseño de los comandos. De no existir
el shell, habrı́a que implementar para cada comando la interpretación de metacaracteres.
Ahora, supongamos que tenemos los archivos arch1, arch2, . . . , arch9.
rm arch[1-46-9]
Elimina todos los archivos, salvo el archivo arch5. Como siempre, el comando no vé los metacaracteres, sino que vé los parámetros arch1, . . . , arch4, arch6, . . . , arch9.
rm [a-z]
El comando rm informarı́a que no encuentra ningún archivo para borrar, pues no hay archivos
cuyos nombres sean exclusivamente caracteres de la a a la z.
rm [a-z]8
Borra el archivo arch8.
rm *[!8]
Borra todos los archivos, salvo arch8.
2.1.1
Nombres de archivos con metacaracteres.
Inmediatamente surje la pregunta de si es posible tener archivos que tengan metacaracteres en
sus nombres, por ejemplo, arch*.
Esto es posible, y si uno no quiere que el shell interprete un metacaracter, debe anteponerle el
metacaracter \ o escribir el metacaracter entre apóstrofes.
Nos referiremos (informalmente) a esta acción como casteo de un caracter.
Por ejemplo:
rm arch
Borra el archivo arch*, y no todos los archivos cuyo nombre comiencen con arch.
rm arch’*’
Tiene el mismo efecto que el anterior.
Sección 2.2. Variables de Ambiente.
2.2
15
Variables de Ambiente.
Algunas propiedades del shell son controladas por una serie de variables de éste, que llamaremos
variables de ambiente.
Algunas variables que tı́picamente usa el shell son:
HOME
contiene el home directory del usuario.
PATH
contiene la lista de directorios, separados por ’:’, donde el shell busca los comandos a ejecutar.
Colocar ’.’ o nada antes de los primeros o últimos ’:’ indica working directory, aunque suele no
setearse por seguridad.
SHELL
contiene el shell que se está ejecutando.
PWD
contiene el working directory.
TERM
contiene el tipo de terminal. Ciertos programas lo utilizan para manejar más eficientemente la
pantalla.
2.2.1
Obteniendo el valor de variables.
Obtener el valor de una variable es la acción de indicarle al shell que interprete el contenido de
la variable.
Los valores de variables se abtienen anteponiendo el caracter $ al nombre de la variable.
Por ejemplo, para ver el contenido de una variable, se puede hacer:
$ echo $HOME
El caracter $ en negrita antes del comando echo representa el prompt del shell, y
no debe ser tipeado. De aquı́ en adelante seguiremos esta convención.
Para agregar un directorio a la variable de ambiente PATH, se puede hacer:
$ PATH=$PATH:/user/games
2.3
Variable de usuario.
Como convención, las variables de ambiente llevan nombres en mayúsculas. Uno puede definir
variables propias, usando nombres en minúsculas.
Sección 2.3. Variable de usuario.
16
Por ejemplo, si uno accede muchas veces a un determinado directorio, podrı́a hacer:
$ midir=/nombre/de/directorio/terriblemente/largo
y simplemente ejecutar:
$ cd $midir
Notar que el auto-completado con la tecla <TAB> también funciona con variables.
2.3.1
Sustitución.
Ya vimos que el shell reemplaza $var por el valor del string asignado a la variable. También,
una variable está configurada, si alguna vez le ha sido asignado un valor, siendo válido el string
nulo como valor para una variable.
Nos centramos ahora en sustituir el valor de una variable, dependiendo de si ésta tenı́a o no un
valor asignado.
Sustitución incondicional.
En este caso, si la variable tenı́a valor, se pierde.
${variable#patron}
${variable##patron}
Si patron coincide con el comienzo del valor de variable , el valor de sustitución
es el valor de variable con la parte coincidente eliminada.
En el primer caso se reemplaza la menor parte coincidente y en el segundo, la mayor
parte coincidente.
${variable%patron}
${variable%%patron}
Si patron coincide con el final del valor de variable , el valor de sustitución es el
valor de variable con la parte coincidente eliminada.
En el primer caso se reemplaza la menor parte coincidente y en el segundo, la mayor
parte coincidente.
Sustitución condicional.
${variable:-cadena}
Si variable está asignada y no es nula el valor de sustitución es el valor de variable ,
sino el valor de sustitución es cadena .
Sección 2.4. Entrecomillado.
17
${variable:=cadena}
Si variable está asignada y no es nula el valor de sustitución es el valor de variable ,
sino el valor de sustitución es cadena , y le asigna este valor a variable .
${variable:+cadena}
Si variable está asignada y no es nula el valor de sustitución es el valor de cadena ,
sino el valor de sustitución es nulo.
${variable:?cadena}
Si variable está asignada y no es nula el valor de sustitución es el valor de variable ,
sino el valor de sustitución es cadena , y sale al shell.
Si cadena es omitido, se imprime el mensaje parameter null or not set. Si se lo
utiliza en un .profile no sale del sistema.
Sirve para verificar si las variables están seteadas.
Los : en la sustitución de variable significa opcional.
2.4
Entrecomillado.
El entrecomillado se utiliza para indicarle al shell que un string, que de otra forma se interpretarı́a
como partes separadas, debe ser interpretado como una unidad.
Por ejemplo, un archivo puede llamarse archivo con nombre largo.txt. El contenido de un
archivo puede mostrarse por la salida standard utilizando el comando cat.
Si tipeamos:
$ cat archivo con nombre largo.txt
El shell le pasarı́a al comando cat los parámetros archivo, con, nombre y largo.txt por
separado. Para que el shell le pase un único parámetro deberı́amos tiperar:
$ cat ’archivo con nombre largo.txt’1
2.4.1
Tipos de entrecomillado.
Distinguimos 3 tipos de entrecomillado:
Comillas. El shell interpreta caracteres especiales.
1
También se podrı́an castear los espacios.
Sección 2.5. Redireccionamiento de la Entrada y Salida.
18
Apóstrofe. El shell no interpreta caracteres especiales.
Acento grave (como en à). El shell ejecuta el comando y pasa la salida.
Por ejemplo:
$ mivar=’es una’
$ echo ’esto $mivar prueba’
esto $mivar prueba
$ echo "esto $mivar prueba"
esto es una prueba
$ echo ‘date‘
Mar, 20 Ago 2002 01:26:43 GMT-03:00
2.5
Redireccionamiento de la Entrada y Salida.
La idea de redirección está sustentada por el concepto que ya mencionamos, en el que todo en
definitiva es un archivo.
Muchos de los comandos que se describirán en capı́tulos posteriores, toman su entrada de la
entrada standard o producen su salida por la salida standard.
Es común que se desee, por ejemplo, la salida de un comando no salga por la salida standard
sino que se almacene en un archivo de texto. Lo mismo ocurre para la entrada de datos a un
comando: puede ser deseable que el comando no espere datos desde la entrada standard sino
que los tome desde un archivo.
Los caracteres > y < permiten la redirección de la salida y la entrada de comandos a o desde
archivos, respectivamente.
2.5.1
Ejemplos.
$ cat arch1 arch2 arch3
Este comando concatena los tres archivos2 por la salida standard.
$ cat arch1 arch2 arch3 > total
Este comando concatena los tres archivos y esta salida se guarda en el archivo total.
Nada se imprime en la salida standard. Si el archivo de redirección no existe, lo crea.
Si existe, lo sobreescribe. Notar que es el shell el que se encarga de este redireccionamiento. Es decir, el comando cat simplemente hace su tarea de concatención,
desentendiéndose de cual será el destino.
2
Es decir, imprime consecutivamente el contenido de los tres archivos en el orden indicado.
Sección 2.6. Interconexión.
19
$ cat arch1 arch2 arch3 >> total
Esto tiene el mismo efecto que en el caso anterior, con la diferencia que si el archivo
de redirección existe, no lo sobreescribe, sino que hace un append.
$ cat arch $ cat < arch
Si bien, ambos casos producen el mismo resultado, en el primer caso, el comando
“ve” que tiene que trabajar con el archivo arch. En el segundo caso, en cambio, es
el shell quien le pasa el contenido del archivo al comando, y por lo tanto el comando
“no se entera” de que trabaja con el archivo, y a sus efectos, “ve” simplemente una
entrada standard. Este ejemplo se menciona con el fin de marcar esta, si bien sutil,
diferencia entre ambos casos.
$ comando-cualquiera 2> archivo-de-errores
Para cada proceso de un sistema UNIX se asignan tres descriptores de archivo: entrada
standard, salida standard, salida standard para errores. Los dos primeros casos ya
los vimos antes. El tercer caso, se refiere a los mensaje de error, que por defecto se
imprimen por la terminal. En muchos casos esto no es deseable3 . Para esto es que el
shell interpreta a 2> como redireccionamiento de la salida standard para errores. Es
decir, cualquier mensaje destinado a la salida standard para errores no se imprimirá
en la terminal, sino que se imprimirá en el archivo archivo-de-errores.
$ comando-cualquiera 2> /dev/null
Esencialmente ocurre lo mismo que antes, aunque en este caso, la redirección es hacia
el archivo /dev/null, el cual representa un archivo nulo: cualquier secuecia de caracteres redireccionado a este archivo será eliminado sin posibilidad de recuperación.
Para hacer una analogı́a, es una suerte de papelera de reciclaje.
$ comando-cualquiera << EOF
El comando toma su entrada desde la entrada standard hasta que se ingrese EOF.
2.6
Interconexión.
La sección anterior se centró en el problema de redireccionamiento. Con esto solo, si se quisiera
conectar dos comandos, se deberia redireccionar la salida de uno a un archivo temporal y que el
segundo comando tome como entrada este archivo.
3
Por ejemplo, en casos en que se deba llevar un log de los errores o el avance del programa.
Sección 2.6. Interconexión.
20
Una de las grandes contribuciones de un sistema operativo UNIX es la posibilidad de interconectar
dos procesos sin necesidad de utilizar archivos temporales auxiliares. Esto se consigue con el
caracter |.
$ who | sort
Este ejemplo es con fines ilustrativos. El comando who imprime por la salida standard
los usuarios loggeados al sistema. El comando sort4 ordena el archivo que se le
especifica. La salida del who no se imprime por la salida standard, sino que se
imprime la del sort, cuya entrada es la salida del comando who.
En esta instancia, debe quedar claro que el objetivo y el propósito de tener estar herramientas
brindadas por el sistema, es tener comandos simples, que al interconectarlos produzcan efectos
más sofisticados.
En capı́tulos posteriores, veremos como lograr esto, mediante lo que se llaman scripts, para luego
ver en detalle el funcionamiento de comandos en detalle.
4
El comando sort se describe en detalle más adelante
Capı́tulo 3
Programación con el Shell:
Shell-Scripting.
En el caso más simple, un script es un archivo con permiso de ejecución que contiene una serie
de comandos que serán ejecutados secuencialmente. Esto salva de estar tipeando esa secuencia
de comandos cada vez que se invoca al script.
Shell-Scripting se remonta a la filosofı́a clásica de UNIX de separar o dividir un problema grande
en problemas más pequeños.
3.1
Comentarios.
El caracter # es el más utilizado para comentarios en shell : éste ignora todo lo que viene después
del caracter numeral.
Por ejemplo:
$ echo hello # there
hello
$ echo hello#there
hello#there
El caracter : también es de comentarios, pero debe usarse al principio de la lı́nea. En verdad,
éste es el comando null del shell.
3.2
Argumentos y Parámetros. El comando shift.
Los parámetros de posición son usados para pasar argumentos desde la lı́nea de comandos a los
scripts. De la misma manera que con las variables, los valores de parámetros se obtienen con el
caracter $ y el dı́gito que indica su posición, siendo $0 siempre el nombre del comando.
21
Sección 3.2. Argumentos y Parámetros. El comando shift.
22
El shell bsh no permite trabajar con más de 10 parámetros directamente, es decir, interpreta a
$10 como el parámetro uno seguido del caracter cero. Para ello se utiliza el comando shift.
Lo que hace shift es pasar el contenido de $1 a $0 y ası́ siguiendo, perdiendo el valor original
de cada variable.
El siguiente es un ejemplo ilustrativo que imprime los argumentos que se pasan al script como
parámetros:
while [ ! -z $1 ]
do
echo $1
shift
done
La sentencia while y la expresión de testeo se explican en las secciones 3.5.2 y 3.3 respectivamente.
3.2.1
Parámetros especiales.
Supongamos que se ejecuta:
$ prog a b c
Entonces vale:
$0
prog
$#
4
$*
a b c seguido de los archivos del working directory
"$*"
a b c *
$$
id del proceso padre
$!
pid del último comando ejecutado en background
$?
estado del último comando ejecutado en foreground
$opciones del shell en efecto
Sección 3.3. Pruebas. El comando test.
3.2.2
23
Estado de salida. El comando exit.
Cada vez que un programa completa su ejecución, retorna un estado al sistema. Este estado es
un número que indica si el programa ha sido ejecutado existosamente o no. Por lo general, el
estado cero indica ejecución exitosa y todo valor distinto de cero indica que la ejecución ha
fallado.
Esto permite, además de la verificación del resultado del programa, el control del mismo en el
manejo de errores y progresión de la ejecución. Como se menciona en el apartado anterior, para
ver el estado de salida, basta ver el valor de $? inmediatamente después de la ejecución del
proceso en cuestión.
Para hacer que un script termine devolviendo un estado en particular, se utiliza el comando
exit n , siendo n el código de terminación. Si no especifica este parámetro, se devolverá el del
último comando ejecutado.
3.3
Pruebas. El comando test.
El comando test permite evaluar el valor de verdad de expresiones lógicas, devolviendo cero en
caso de éxito, o distinto de cero en caso contrario.
El formato de este comando1 es:
test expresión
o
[ expresión ]
expresión contendrá un conjunto de operadores que describiremos a continuación, según la
prueba. También, expresión debe estar rodeada por espacios y debe entrecomillarse para
embeber los espacios dentro de ella.
3.3.1
Operadores del comando test.
! . . . . . . negación
-a . . . . . . AND
-o . . . . . . OR
3.3.2
Pruebas sobre archivos.
Algunos tipos de prueba sobre archivos son:
1
]].
tanto para Bourne Shell como para Korn Shell, permitiendo este último la prueba mediante [[ expresión
Sección 3.4. Aritmética entera. El comando expr.
-a file
-d file
-f file
-L file
-p file
-s file
-r file
-w file
-x file
file1 -nt file2
file1 -ot file2
3.3.3
A
A
A
A
A
A
-eq
-ge
-gt
-le
-lt
-ne
3.3.4
24
. . . . . . file existe.
. . . . . . file existe y es un directorio.
. . . . . . file existe y es un archivo regular.
. . . . . . file existe y es un link simbólico.
. . . . . . file existe y es una named pipe.
. . . . . . file existe y no es vacı́o.
. . . . . . file existe y tiene permiso de lectura.
. . . . . . file existe y tiene permiso de escritura.
. . . . . . file existe y tiene permiso de ejecución.
. . . . . . file1 es más nuevo que file2 .
. . . . . . file1 es más antiguo que file2 .
Prueba de valores para operaciones algebraicas.
B
B
B
B
B
B
. . . . . . igual a
. . . . . . mayor o igual a
. . . . . . mayor a
. . . . . . menor o igual a
. . . . . . menor a
. . . . . . distinto de
Prueba de valores para cadena de caracteres.
Debido a que una cadena puede contener nulos o espacios intermedios, siempre es aconsejable
entrecomillar a la variable con comillas dobles para evitar errores en el comando test.
string1 = string2 . . . . . . las cadenas son iguales
string1 != string2 . . . . . . las cadenas no son iguales
string . . . . . . la cadena no es nula
-z string . . . . . . la cadena tiene longitud cero (es nula)
-n string . . . . . . la cadena no es nula
3.4
Aritmética entera. El comando expr.
En Bourne Shell, todas las variables son strings. Las operaciones matemáticas entre strings no
son posibles, pero existe una forma de evaluar una expresión tipo string como una expresión
matemática, utilizando el comando expr.
expr evalúa sus argumentos como una expresión matemática y devuleve el resultado a la salida
standard.
Las operaciones disponibles son: +, -, *, % (resto) y /.
Cuando se utilicen estos operadores deberá haber un espacio a ambos lados del mismo.
Sección 3.5. Comandos de control.
25
Hay también una operación de equiparación, :, que compara el primer argumento con el segundo. El segundo debe ser una expresión regular (a ver más adelante). La operación retorna
el número de caracteres coincidentes, o cero si no hay coincidencia. Al utilizar una expresión
regular coincidente con todo, .*, el operador de equiparación puede ser usado para determinar
la longitud del primer argumento.
Si se ejecuta una expresión entre comillas simples, el resultado reemplaza a la expresión misma.
Recordar que $, *, etc., deben estar casteados para que no sean interpretados por el shell.
Ejemplo.
$
$
$
3
a=’expr 1 + 2’
b=’expr $a \* 4’
echo $a $b
12
3.4.1
Operador de longitud.
${#variable}
Devuelve la longitud de variable .
3.5
Comandos de control.
Los comandos de control pueden dividirse en dos grupos:
• sentencias de decisión
• sentencias de iteración
3.5.1
Sentencias de Decisión.
Sentencia if.
Formato:
if condición
then
comandos
[elif condición
then
comandos ]
Sección 3.5. Comandos de control.
26
[else
comandos ]
fi
Ejemplo.
El siguiente script determina si el archivo pasado como parámetro existe y tiene un tamaño
mayor a cero.
if test -s "$1"
then
echo $1 es un archivo existente con tama~
no mayor a cero.
else
echo $1 no existe o tiene tama~
no nulo.
fi
Sentencia case.
Es utilizada para la selección de múltiples alternativas. Cada posibilidad es conocida como
branch y cada branch debe estar separada por ;;, siendo opcional en el último branch.
La variable en la sentencia case debe ser una coincidencia explı́cita: no debe haber expresiones regulares o nombres de archivos referenciados con comodines. Sı́ es posible usar la
condición OR que puede ser utilizada en los patrones, representada por |.
Los metacaracteres pueden usarse en los patrones con el siguiente significado:
• * : cero o más ocurrencias de uno o todos los caracteres.
• ? : cualquier caracter.
• [] : configura y determina rangos.
Formato:
case valor in
pat1)
comandos
;;
pat2)
comandos
;;
...
patN)
comandos
Sección 3.5. Comandos de control.
27
;;
*)
comandos por defecto
;;
esac
Ejemplo.
El siguiente script muestra un pequeño menú para determinar que hacer con el archivo pasado
como parámetro.
if test $#
then
Uso: $0
exit 1 #
fi
if test !
-ne 1 # verificamos que se pase un parámetro
archivo # $0 es el nombre del script
salimos devolviendo un código de terminación de error por uso erróneo
-f "$1" # verificamos la existencia del archivo
then
echo $1 no es un nombre de archivo válido.
exit 2 # salimos devolviendo un código de terminaci’on de error por archivo no
válido
fi
echo ¿Qué desea hacer con $1?: # presentamos un menu
echo
echo
echo
read
’<I> para imprimirlo.’
’<B> para borrarlo.’
’<otra-tecla> para salir.’
accion # leemos la opcion que se ingrese
case $accion in
I|i) lp $1 ;;
B|b) rm $1 ;;
*) echo Saliendo sin hacer nada...
esac
;;
En este ejemplo se introdujeron los comandos read, para leer de la entrada standard el valor
para una variable, y el comando lp para formatear e imprimir archivos.
Sentencia select.
Esta sentencia, solo disponible en Korn Shell, permite un listado de selección por menú. Este
comando usa la variable de ambiente PS3 para el prompt, y COLUMNS y LINES para determinar
la apariencia del menú.
Sección 3.5. Comandos de control.
28
Formato:
select variable in arg1 arg2 ...argN
do
comandos
done
El usuario selecciona el elemento de la lista sobre la cual ejecutará los comandos , los cuales
se continuarán ejecutando hasta que se encuentre con comandos de ruptura, tales como break,
exit o return.
Ejemplo.
PS3="Elija uno: "
select i in 6109 6110 6620 7506 7542 exit
do
case $i in
6109) echo $1 Probabilidad y Estadistica B ;;
6110) echo $1 Analisis Matematico III ;;
6620) echo $1 Organizacion de Computadoras ;;
7506) echo $1 Organizacion de Datos ;;
7542) echo $1 Taller de Programacion I ;;
exit) echo Saliendo...
exit 0 ;;
*) echo Seleccion invalida ;;
esac
read rta?"Continuar? (s/n)? "
if [ $rta != ’s’ ]
then
echo Fin del menu
exit 0
fi
done
3.5.2
Sentencias de Iteración.
Sentencia for.
Formato:
for variable in lista
do
Sección 3.5. Comandos de control.
29
comandos
done
o alternativamente
for variable in lista ; do comando1 ; ...; comandoN ; done
La lista puede ser enunciada explı́citamente o ser el resultado de otro comando o metacracteres.
Para cada iteración, variable toma el valor de cada uno de los elementos de lista , concluyendo
el ciclo cuando se llegue al último elemento de lista .
Sentencia while.
Esta sentencia ejecuta los comandos mientras la condicion sea verdadera.
Formato:
while condicion
do
comandos
done
Sentencia until.
Esta sentencia cicla hasta que condicion se cumpla.
Formato:
until condicion
do
comandos
done
Hasta acá se tienen vistas varias de las herramientas que brinda el sistema. Pasaremos ahora a
estudiar comandos simples en detalle.
Capı́tulo 4
Comandos de Entrada y Salida.
Estudiaremos ahora comandos del sistema en detalle. Dado que muchos de ellos incluyen opciones muy especı́ficas y fuera del alcance de este apunte, se sugiere consultar las manual pages
correspondientes para mayor información.
4.1
Traducción de caracteres: el comando tr.
El comando tr es un filtro utilziado para traducir los caracteres desde la entrada standard hacia
la salida standard.
Sintaxis:
tr [charset1 ] [charset2 ]
Notar que la sintaxis no especifica archivos. Para trabajar con archivos, el ingreso debe ser
redireccionado desde la lı́nea de comandos.
Los rangos y conjuntos pueden ser utilizados como un mapeo de caracteres de uno en uno. Si
charset2 es más corto que charset1 , entonces charset2 es completado con la repetición del
último caracter en el conjunto.
4.1.1
Ejemplos.
Para el ejemplo utilizaremos el siguiente archivo, que llamaremos arch:
Mercurio
Urano
Tierra
Marte
Neptuno
G.
B.
F.
B.
T.
Total
Total
Total
Total
Total
horas
horas
horas
horas
horas
80
78
80
40
80
$ tr 8 2 < arch
30
Sección 4.2. El comando cut.
Mercurio
Urano
Tierra
Marte
Neptuno
G.
B.
F.
B.
T.
Total
Total
Total
Total
Total
horas
horas
horas
horas
horas
31
20
72
20
40
20
$ tr [a-z] [A-Z] < arch
MERCURIO
URANO
TIERRA
MARTE
NEPTUNO
4.2
G.
B.
F.
B.
T.
TOTAL
TOTAL
TOTAL
TOTAL
TOTAL
HORAS
HORAS
HORAS
HORAS
HORAS
80
78
80
40
80
El comando cut.
El comando cut puede ser usado para cortar columnas desde una tabla o campos de un archivo.
Los campos cortados no necesariamente tiene que ser de longitud fija.
Sintaxis:
cut -lista [arch1 arch2 ...archN ]
Si no se le indica ningún archivo, toma como entrada la entrada standard.
El modificador lista puede ser:
-ci
-ci,j,k
-ci-j
-ci -
El caracter i -ésimo.
Los caracteres i -ésimo, j -ésimo y k -ésimo.
Desde el caracter i -ésimo hasta el j -ésimo.
A partir del caracter i -ésimo.
El comando cut empieza a contar los caracteres desde 1.
Esto funciona muy bien en los archivos que posean un formato bien definido, como la salida del
comando who1 . Como alternativa se tiene la especificación de campos a cortar:
• Con la opción -dcaracter se le especifica al comando cut el caracter que debe tomar
como separador de campos.
• La opción -flista especifica el campo o campos que serán cortados.
• La opción -s indica que no se impriman aquellas lı́neas que no contienen al separador de
campos.
1
El comando who lista información sobre los usuarios loggeados al sistema. Los nombres de usuario son los
caracteres del 1 al 8, las terminales son del 12 al 24 y las fecha y hora del login son del 25 al 36.
Sección 4.3. El comando paste.
4.2.1
32
Ejemplos.
$ who
root
user1
user2
user3
term/01
term/00
term/02
term/03
Apr
Apr
Apr
Apr
12
12
12
12
08:00
09:01
09:13
09:15
$ who | cut -c1-5
root
user1
user2
user3
$ who | cut -c1-5,19root
user1
user2
user3
Apr
Apr
Apr
Apr
12
12
12
12
08:00
09:01
09:13
09:15
Sea ahora el archivo infou:
root:x:0:0:Super User:/:/bin/ksh
cron:NONE:1:1:Time Daemon:/:
user1::100:101:555 1212:/home/user1:/bin/sh
$ cut -d:
-f1,6 infou
root:/
cron:/
user1:/home/user1
4.3
El comando paste.
El comando paste funciona en cierta forma a la inversa del comando cut: yuxtapone columnas.
Distinas sintaxis:
paste arch1 arch2 ...archN
Esta es la forma más simple de uso, en la que cada lı́nea de cada archivos se ponen
juntas separadas por una tabulación.
Sección 4.3. El comando paste.
33
paste -d lista arch1 arch2 ...archN
En este caso, en lugar de utilizar el separador por defecto, paste utiliza como separadores los caracteres indicados en lista .
paste -s [-d lista ] arch1 arch2 ...archN
Se utiliza para pegar lı́neas dentro de un mismo archivo.
paste - arch1 [arch2 ...archN ]
Indica que además de los archivos indicados, debe tomar una entrada que le está
siendo redireccionada.
4.3.1
Ejemplos.
Supongamos los siguientes tres archivos:
ciudades
Atlanta
New York
Los Angeles
nombres
user1
user2
user3
telefonos
(404)555-5356
(212)555-3456
(213)555-1234
$ paste nombres telefonos
user1
user2
user3
(404)555-5356
(212)555-3456
(213)555-1234
$ paste -d’=+’ nombres ciudades telefonos
user1=Atlanta+(404)555-5356
user2=New York+(212)555-3456
user3=Los Angeles+(213)555-1234
$ paste -s nombres
user1
$ cut -d:
user2
user3
-f5 clientes1 | paste - clientes2
Capı́tulo 5
Expresiones Regulares.
Las expresiones regulares (REs) son patrones que describen strings y se usan para matchear 1
esos strings. Las expresiones regulares permiten, por ejemplo, seleccionar algún conjunto de
registros de un campo de un archivo de datos. El espectro de aplicación varı́a desde algo simple
como el reemplazo por parte del shell del caracter * por todos los archivos de un directorio hasta
matcheos más refinados como los que utilizan comandos como grep y awk.
Las expresiones regulares se construyen a partir de caracteres ordinarios y metacaracteres. Los
caracteres ordinarios se matchean a sı́ mismos, mientras que los metacaracteres matchean distintos grupos de caracteres o modifican la operación de otros caracteres.
En UNIX tenemos tres tipos o niveles de expresiones regulares:
1. los del shell, para nombres de archivos, de los cuales ya se habló antes;
2. los simples, utilizados por comandos como grep y sed;
3. los extendidos, utilizados por comandos como egrep.
Para los tres casos, se cumple:
• La barra invertida \ se usa para castear un caracter, es decir, todo caracter que siga a una
barra invertida se tomará como una caracter ordinario, inclusive si éste es un metacaracter.
• Caracteres entre corchetes [] representan un solo caracter matcheado de todos los del
conjunto.
– Si el primer caracter de un conjunto es el acento circunflejo ^ se matchea el complemento del conjunto, es decir, todo lo no perteneciente al conjunto.
– Si se utiliza el guión -, se está indicando un rango de caracteres.
1
En este apunte vamos a usar este término para significar corresponder o coincidir, por falta de un verbo que
exprese más precisamente el verbo inglés to match.
34
Sección 5.1. Expresiones regulares simples.
35
Por Ejemplo.
abcde
[abcde]
[a-e]
[^a-e]
\[\]\\
5.1
Los caracteres ’a’, ’b’, ’c’, ’d’ y ’e’ se matchean en ese orden.
Uno de los caracteres ’a’, ’b’, ’c’, ’d’ o ’e’ se matchean.
Idem anterior.
Un caracter, salvo ’a’, ’b’, ’c’, ’d’ o ’e’, se matchean.
Los caracteres ’[’, ’]’, ’\’ se matchean en ese orden.
Expresiones regulares simples.
Aparte de los caracteres ya mencionados, las expresiones regulares simples brindan los siguientes
metacaracteres:
• El asterisco * significa repetir la RE anterior a él un número arbitrario de veces, incluyendo
ninguna vez.
• El punto . matchea un caracter cualquiera.
• El acento circunflejo ^ en este caso está sobrecargado: solo tiene sentido como primer
caracter de una RE, caso en el cual significa matchear el comienzo de la lı́nea.
• El signo de pesos $ solo tiene sentido como último caracter de una RE, caso en el cual
significa matchear el final de la lı́nea.
El comando grep trabaja con llaves, cuando son casteadas, para denotar una cantidad de ocurrencias de la RE que precede:
\{n\}
\{n,\}
\{n,m\}
Exactamente n ocurrencias.
Por lo menos n ocurrencias.
Entre n y m ocurrencias.
También, el editor vi trabaja con paréntesis angulares <> para indicar comienzo o final de una
palabra, respectivamente.
5.1.1
Algunos ejemplos de expresiones regulares simples.
p[aeo]lo
Alguno de ’palo’, ’pelo’, ’polo’.
^$
Una lı́nea en blanco (matchear comienzo, nada, y fin).
^[a-zA-Z]$
Sección 5.2. Expresiones regulares extendidas.
36
Lı́neas de una sola palabra.
^[0-9]$
Lı́neas con exactamente un número.
d.n
Cualquier secuencia de tres caracteres comenzando con una ’d’ y terminando con
una ’n’.
d[aeiou]n
’dan’, ’den’, ’din’, ’don’, or ’dun’.
4[2-9][0-9][0-9]-[0-9]\{4\}
Un nḿero telefónico del Gran Buenos Aires: un cuatro, un dı́gito entre dos y nueve,
dos dı́gitos, un guión y cuatro dı́gitos.
5.2
Expresiones regulares extendidas.
Las expresiones regulares extendidas agregan paréntesis para agrupar.
• La barra vertical (o pipe) | para alternar.
• El signo más + para repetir el item precedente por lo menos una vez.
• El signo de interrogación ? para matchear el item precedente ninguna o una vez.
5.2.1
Ejemplos de REs Extendidas.
(Andrea|Beatriz|Carla) (Dieguez|Fernandez)
Matchea alguno de los seis nombres ’Andrea Dieguez’, ’Andrea Fernandez’, ’Beatriz
Dieguez’, ’Beatriz Fernandez’, ’Carla Dieguez’ o ’Carla Fernandez’.
[0-9]+
Matchea un número entero (uno o más dı́gitos).
(\+|-)?[0-9]+
[+-]?[0-9]+
Matchea un número entero que puede o no llevar signo (un signo más, un signo menos
o nada, seguido de un número entero).
Further articles in this series will focus on various utilities which use REs to select data for
processing–grep, egrep, sed, and awk.
Referencias
[1] Apunte de “Entorno UNIX” por Paola Chamoles.
Año 1999.
75.08—Sistemas Operativos.
[2] Red-Hat Official Installation Guide.
http://www.redhat.com/docs/manuals/linux/RHL-7.2-Manual/install-guide/
[3] Manual page del shell bash.
37
Descargar