5. LA UTILIDAD make La utilidad make se utiliza para mantener actualizado un conjunto de programas ejecutables. Esto se basa en los tiempos de modificación de los programas y el código fuente del que depende cada programa. La utilidad examinará las líneas de dependencia en un archivo llamado makefile en el directorio de trabajo actual. Estas líneas de dependencia indican relaciones entre archivos y especifican un archivo de destino que depende de uno o más archivos de requisitos previos. Si modificó alguno de los archivos de requisitos previos más recientemente que el archivo de destino, make actualizará el archivo de destino según los comandos de construcción que siguen a las líneas de dependencia. +===============================================================+ | Command Format: make [options] [target_files] | | | | See the online man pages for a detailed list of options | | | +===============================================================+ Los target_files hacen referencia a los destinos en las líneas de dependencia del archivo llamado makefile. Si no especifica un target_file, make actualizará la primera línea de dependencia que encuentre en makefile. El makefile tiene la siguiente construcción: target: prerequisite_list tab construction_commands La línea de dependencia está compuesta por target y prerequisite_list, separados por dos puntos. Los construction_commands deben comenzar con un carácter de tabulación y deben seguir a la línea de dependencia. El target es el nombre del archivo que depende de los archivos en prerequisite_list. Los construction_commands son comandos de shell que construyen el target; estos suelen ser comandos de compilación. La utilidad make ejecutará los construction_commands cuando la hora de modificación de uno o más de los archivos en prerequisite_list sea más reciente que el target. Ejemplo de archivo makefile: payroll: sales.c salary.c cc sales.c salary.c -o payroll En el ejemplo, el destino se llama payroll. Depende de sales.c y salary.c. Si la hora de modificación de cualquiera de estos es más reciente que payroll, se ejecutarán los comandos de construcción. En este caso, los programas de código fuente se compilan y almacenan en payroll. En el ejemplo anterior, para que se produzca la actualización, simplemente escriba make. Ejemplo: ................................................................. . $make . ................................................................. Dado que no se especificó ningún objetivo, la primera línea de dependencia es la que make intentará ejecutar. Cada uno de los requisitos previos de una línea de dependencia puede ser un objetivo en otras líneas de dependencia. Esta anidación de especificaciones puede continuar, creando una jerarquía compleja que puede especificar un gran sistema de programas. Archivo make de ejemplo: form: size.o length.o cc size.o length.o -o form size.o: size.c form.h cc -c size.c length.o: length.c form.h cc -c length.c form.h: num.h table.h cat num.h table.h > form.h Tenga en cuenta que form depende de dos archivos de objeto, size.o y length.o. Estos dos archivos de objeto dependen, a su vez, de sus respectivos programas de código fuente y del archivo de encabezado, form.h. El archivo de encabezado depende de otros dos archivos de encabezado. Tenga en cuenta que los comandos de construcción para form.h pueden utilizar cualquier comando de shell; en este caso, cat crea el archivo de encabezado. Este archivo make puede ser bastante difícil de escribir, especialmente si existen varias interdependencias. La utilidad make puede confiar en las dependencias implícitas y los comandos de construcción para facilitar su trabajo de escritura del archivo make. Si no incluye una línea de dependencia para un archivo, make supone que los archivos de programa de objeto dependen de los archivos de código fuente del compilador o ensamblador. Si un requisito previo para un archivo de destino es .o y .o no es un destino con sus propios requisitos previos, make buscará uno de los siguientes archivos en el directorio de trabajo actual. Nombre de fichero Tipo de fichero .c C source code .f FORTRAN source code .s Assembler source code Si no incluye un comando de construcción para uno de los archivos enumerados, make creará una línea de comando de construcción predeterminada que llamará al compilador o ensamblador apropiado para crear el archivo de objeto. grep: UN FILTRO DE COINCIDENCIA DE PATRONES La utilidad grep puede buscar en un archivo para ver si contiene una cadena de caracteres específica. La utilidad no cambiará el archivo que busca, sino que mostrará cada línea que contenga la cadena. El formato de la cadena es el siguiente. EIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII? | Command Format: grep [options] limited_regular-expression [file] | | | | Use the man command for a complete list of options | | | EIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII? La utilidad grep busca un patrón en los archivos y muestra todas las líneas que lo contienen. Utiliza expresiones regulares limitadas (son expresiones que tienen valores de cadena que utilizan un subconjunto de todos los caracteres alfanuméricos y especiales posibles) como las que se utilizan con ed para encontrar los patrones. Tenga cuidado al utilizar los caracteres $, *, [, ^, |, (, ) y \ en la expresión regular porque el Shell los evaluará. Es una buena práctica encerrar la expresión regular entre comillas simples. Esto evitará que el Shell evalúe estos caracteres especiales. La utilidad grep asumirá la entrada estándar si no se proporcionan archivos. Normalmente, cada línea que se encuentre en el archivo se mostrará en la salida estándar. Sesión de Ejemplo: ................................................................. . $grep 'disc' memo . ................................................................. Este comando buscará la cadena "disc" en el archivo "memo". Incluirá palabras como discover e indiscreet porque contienen los caracteres "disc". Las comillas simples no son necesarias y, para este ejemplo, no habrían hecho ninguna diferencia. Le permiten incluir espacios en el patrón de búsqueda. 5.0.1 Más sobre expresiones regulares El comando grep se puede entender mejor con una discusión sobre expresiones regulares. Creemos una base de datos de números de teléfono llamada phone.lis y luego usemos expresiones regulares para buscar en la base de datos. Aquí hay una lista de los contenidos de phone.lis Sesión de Ejemplo: +---------------------------------------------------------------+ | $cat phone.lis | | Smith, Joan 7-7989 | | Adams, Fran 2-3876 | | StClair, Fred 4-6122 | | Jones, Ted 1-3745 | | Stair, Rich 5-5972 | | Benson, Sam 4-5587 | | $ | +---------------------------------------------------------------+ El formato de los registros de esta base de datos es: Apellido, Nombre #-#### Utilizando la base de datos (phone.lis) anterior, ¿qué comando grep utilizaríamos para buscar en la base de datos y obtener todos los registros que tenían una persona cuyo nombre contiene una "S"? Un carácter alfabético se representa a sí mismo. +---------------------------------------------------------------+ | $grep S phone.lis | | Smith, Joan 7-7989 | | StClair, Fred 4-6122 | | Stair, Rich 5-5972 | | Benson, Sam 4-5587 | | $ | +---------------------------------------------------------------+ Este comando grep buscó la cadena "S" y luego enumeró todas las líneas en phone.list que coincidían. Se utiliza un solo . (punto) para representar cualquier carácter individual. Sesión de Ejemplo: +---------------------------------------------------------------+ | $grep .S phone.lis | | Benson, Sam 4-5587 | | $ | +---------------------------------------------------------------+ Un $ representa el final de la línea. Sesión de Ejemplo: +---------------------------------------------------------------+ | $grep 5$ phone.lis | | Jones, Ted 1-3745 | | $ | +---------------------------------------------------------------+ Un ^ representa el comienzo de la línea. Sesión de Ejemplo: +---------------------------------------------------------------+ | $grep ^S phone.lis | | Smith, Joan 7-7989 | | StClair, Fred 4-6122 | | Stair, Rich 5-5972 | | $ | +---------------------------------------------------------------+ Las expresiones regulares deben llegar a grep para que se puedan evaluar correctamente. Supongamos que queremos obtener los registros de los empleados que tienen un número de teléfono que comienza con "4". ¿Qué hace la siguiente expresión? Sesión de Ejemplo: +---------------------------------------------------------------+ | $grep 4 phone.lis | | StClair, Fred 4-6122 | | Jones, Ted 1-3745 | | Benson, Sam 4-5587 | | $ | +---------------------------------------------------------------+ ¿Por qué obtuvimos el registro de Ted Jones? El carácter de tabulación fue evaluado por el Shell y por lo tanto la búsqueda se realizó buscando un "4". Esto es lo mismo que si hubiéramos ingresado $grep 4 phone.lis. Debemos evitar que el Shell evalúe estos caracteres, esto se hace con el carácter \ (barra invertida) como se muestra en el siguiente ejemplo. Sesión de Ejemplo: +---------------------------------------------------------------+ | $grep \4 phone.lis | | StClair, Fred 4-6122 | | Benson, Sam 4-5587 | | $ | +---------------------------------------------------------------+ Ahora funcionó correctamente. Buscó un carácter seguido del número 4. Los [] (corchetes izquierdo y derecho) se utilizan para identificar un rango de caracteres. Sesión de Ejemplo: +---------------------------------------------------------------+ | $grep \[AF] phone.lis | | Adams, Fran 2-3876 | | StClair, Fred 4-6122 | | $ | +---------------------------------------------------------------+ ¿Por qué es necesario poner [] entre comillas? En el ejemplo anterior, la búsqueda realiza una coincidencia con "A" o "F". Un guión puede indicar inclusión. Por ejemplo, queremos realizar una coincidencia con un número de teléfono que contenga un 1, 2, 3 o 4. ¿Cómo se puede hacer esto? A continuación, se muestra un ejemplo: Sesión de Ejemplo: +---------------------------------------------------------------+ | $grep \[1-4] phone.lis | | Adams, Fran 2-3876 | | StClair, Fred 4-6122 | | Jones, Ted 1-3745 | | Stair, Rich 5-5972 | | Benson, Sam 4-5587 | | $ | +---------------------------------------------------------------+ El carácter ^ busca todos los caracteres que NO estén dentro de los corchetes []. Por ejemplo, [^0-9] coincide con todos los caracteres que NO SEAN dígitos [^a-zA-Z] coincide con todos los caracteres que NO SEAN alfabéticos NOTA: dentro de los corchetes [], tanto \, *, y $ pierden su significadode metacaracter. Además, el carácter ^ es especial solo si aparece al principio. ¿Qué busca el siguiente comando? Sesión de Ejemplo: +---------------------------------------------------------------+ | $grep '[^789]$' phone.lis | | Adams, Fran 2-3876 | | StClair, Fred 4-6122 | | Jones, Ted 1-3745 | | Stair, Rich 5-5972 | | $ | +---------------------------------------------------------------+ 5.0.2 Más expresiones regulares El * (asterisco) representa una cantidad cero o más de los caracteres que preceden al asterisco. A* representa 0 o más A. AA* representa 1 o más A. [0-9]*$ representa 0 o más dígitos al final de una línea (los últimos cuatro dígitos de un número de teléfono) .* representa 0 o más de cualquier carácter. ¿Cómo escribirías un comando grep recurriendo a expresiones regulares para encontrar el apellido que comienza con una "S" y el nombre con una "F"? ^S Comienza con una "S" .*,F Cualquier número de caracteres antes de ,F Sesión de Ejemplo: +---------------------------------------------------------------+ | $grep ^S.\*,F phone.lis | | StClair, Fred 4-6122 | | $ | +---------------------------------------------------------------+ NOTA: El asterisco * se ha entrecomillado para que el Shell no intente evaluarlo. Es muy conveniente entrecomillar toda la cadena para evitar que el Shell realice una expansión o sustitución. También aumenta la legibilidad de la expresión regular, como en el siguiente ejemplo. Sesión de Ejemplo: +---------------------------------------------------------------+ | $grep '^S.*, F' phone.lis | | StClair, Fred 4-6122 | | $ | +---------------------------------------------------------------+ 5.0.3 Algunas opciones interesantes de grep El grep ofrece varias opciones que modifican la forma en que se realiza la búsqueda. -c Informa solo un recuento de líneas coincidentes -v Imprime las líneas no coincidentes con el patrón. ¿Qué imprimirán estas líneas? Sesión de Ejemplo: +---------------------------------------------------------------+ | $grep -c '[J-Z]' phone.lis | | 5 | | $ | +---------------------------------------------------------------+ ¿Por qué obtuvimos este resultado? Analicemos el comando. En castellano, este comando podría interpretarse como "Dime cuántos registros del archivo "phone.lis" contienen una letra del conjunto J a Z inclusive". Se analiza el archivo phone.lis y observa que cinco registros cumplen con esta restricción. Por lo tanto, la respuesta es 5. Ahora analiza este otro ejemplo y observe lo que hace. Sesión de Ejemplo: +---------------------------------------------------------------+ | $grep -v '[J-Z]' phone.lis | | Adams,Fran 2-3876 | | $ | +---------------------------------------------------------------+ ¿Por qué este es el único registro encontrado? La opción -v indica que se seleccionen los registros que NO coincidan con el patrón. Este es el mismo patrón que el ejemplo anterior y, por lo tanto, selecciona los registros que no coinciden con el patrón. El registro "Adams" es el único que no coincide, puesto que NO tiene un carácter del conjunto J a Z. 5.0.4 Resumen de caracteres de expresiones regulares ^ Principio de la línea $ Fin de la línea * 0 o más caracteres anteriores . Cualquier carácter individual [...] Un rango de caracteres [^...] Rango de exclusión de caracteres sed: EDITAR UN ARCHIVO A SALIDA ESTÁNDAR UNIX proporciona un método para editar secuencias de datos. Es la utilidad sed. El nombre de esta utilidad se deriva de Stream EDitor. No es lo mismo que el editor vi. El editor vi edita texto en un archivo. La utilidad sed edita texto en una secuencia. Para editar una secuencia de caracteres se requieren dos cosas. Primero, se debe identificar la línea a editar (expresiones regulares) y segundo, cómo editar la línea. +===============================================================+ | Command Format: sed [-n] [-e script] [-f sfile] [files] | | | | Details in on-line man pages | +===============================================================+ La utilidad sed copia los archivos nombrados (entrada estándar predeterminada) a la salida estándar, editados de acuerdo con un conjunto (script) de comandos. Las opciones -f hacen que el script se tome del archivo "sfile". La forma general es: $ sed /address/instruction NOTA: Si no se especifica ninguna dirección, se eligen todas las líneas para editar. Las direcciones 'sed' pueden ser números de línea o expresiones regulares. Ejemplo: números de línea 2,4 2,$ ($ representa la última línea) dirección textual /regular-expression/ NOTA: Las barras diagonales encierran las direcciones textuales Las instrucciones sed indican qué función de edición realizar. A continuación, se muestran algunas instrucciones sed útiles: s reemplazar d borrar NOTA: La mayoría de las líneas de comando sed contienen espacios o metacaracteres y deben estar entre comillas para protegerlas del Shell. Hay muchos más comandos de edición proporcionados por sed. El siguiente es un ejemplo de comando sed para editar los registros en el archivo de base de datos con el que ya estamos familiarizados; es decir, phone.lis. Sesión de Ejemplo: +---------------------------------------------------------------+ | $sed /s/Smith/Smythe/ phone.lis | | Smythe, Joan 7-7989 | | Adams, Fran 2-3876 | | StClair, Fred 4-6122 | | Jones, Ted 1-3745 | | Stair, Rich 5-5972 | | Benson, Sam 4-5587 | | $ | +---------------------------------------------------------------+ sed es un editor. Simplemente copia la entrada estándar a la salida estándar, editando las líneas que coinciden con la dirección indicada. El archivo original no se modifica. A continuación se muestra otro ejemplo de un comando sed. Sesión de Ejemplo: +---------------------------------------------------------------+ | $sed '2,4 s/2$/3/' phone.lis | | Smith, Joan 7-7989 | | Adams, Fran 2-3876 | | StClair, Fred 4-6123 | | Jones, Ted 1-3745 | | Stair, Rich 5-5972 | | Benson, Sam 4-5587 | | $ | +---------------------------------------------------------------+ ¿Qué hace este comando sed? Si lees el comando en inglés, se lee así: En las líneas 2 a 4, sustituye el 2 al final de la línea por un 3. Observa que el número de teléfono de StClair, Fred cambió de 4-6122 a 4-6123. El número de Stair, Rich no cambió porque estaba fuera del rango. La utilidad sed también se puede utilizar para eliminar partes de una línea de datos. Esto se hace sustituyendo por nada las partes que quieres eliminar. Se ve así: Sesión de Ejemplo: +---------------------------------------------------------------+ | $sed 's/^.*, //' phone.lis | | Joan 7-7989 | | Fran 2-3876 | | Fred 4-6122 | | Ted 1-3745 | | Rich 5-5972 | | Sam 4-5587 | | $ | +---------------------------------------------------------------+ Al leer este comando, se entiende lo siguiente: Sustituir desde el principio de la línea seguido de cualquier número de caracteres seguido de una coma con la cadena nula (nada). Esto tiene el efecto de eliminar el texto. A continuación se muestra un comando de eliminación y cómo se utiliza. Sesión de Ejemplo: +---------------------------------------------------------------+ | $sed d phone.lis | | $ | +---------------------------------------------------------------+ ¿Por qué no hay salida? Bueno, leyó la entrada estándar y realizó la operación de edición en todas las líneas seleccionadas. Como no se especificó ninguna línea, se seleccionaron todas las líneas para editarlas. La edición realizada fue la eliminación de la línea. Pregunta: ¿Se destruyó el archivo original? Se permiten varios comandos en sed. Cada instrucción se aplica a cada línea de entrada. Sesión de Ejemplo: +---------------------------------------------------------------+ | $sed '/Stair/d | | >/Adams/d' phone.lis | | Smith, Joan 7-7989 | | StClair, Fred 4-6122 | | Jones, Ted 2-1136 | | Benson, Sam 4-5587 | | $ | +---------------------------------------------------------------+ Los registros de Adams y Stair se han eliminado de la base de datos. NOTA: El carácter > es el prompt secundario de BourneShell. awk: UN LENGUAJE DE PROGRAMACIÓN DE COINCIDENCIA DE PATRONES Supongamos que desea cambiar el formato de la base de datos phone.lis para que sea el primer nombre seguido del apellido. No hay una manera fácil de hacer esto con sed. Afortunadamente, UNIX no solo proporciona un editor de secuencias (sed), sino que también tiene una herramienta de formato. La herramienta de formato en UNIX se llama awk. Esta herramienta recibe su nombre de los autores que la escribieron, Alfred V. Aho, Peter J. Weinberger y Brian W. Kerninghan, por lo que realmente no tiene ningún significado. La utilidad awk es un lenguaje de escaneo y procesamiento de patrones. Buscará uno o más archivos para un patrón específico y luego realizará una acción, como escribir en la salida estándar o incrementar un contador al encontrar una coincidencia. Puede usar awk para generar informes o filtrar texto. Funciona igualmente bien con números o texto. Los autores lo diseñaron para que fuera fácil de usar y a este fin sacrificaron la velocidad de ejecución. Mientras que la utilidad sed nos permite cambiar el texto en un flujo, awk nos permite reorganizar, agregar o eliminar texto en un flujo con facilidad. Awk aprovecha muchas construcciones del lenguaje de programación C. Tiene las siguientes características: formato flexible ejecución condicional declaraciones de bucle variables numéricas variables de cadena expresiones regulares printf de C Awk tomará su entrada de los archivos que especifique en la línea de comandos o de la entrada estándar. El siguiente es el formato de awk: +===============================================================+ | Command format: awk [-Fc] [prog] [files] | +===============================================================+ El awk escaneará cada línea del archivo en busca de líneas que coincidan con un conjunto de patrones especificados por prog. Con cada patrón en prog puede haber una acción asociada que se realizará cuando se encuentre la línea. El conjunto de patrones puede aparecer literalmente como prog, o en un archivo especificado como -f file. La cadena prog debe estar entre comillas simples para protegerla del Shell. Los archivos se leen en orden y si no se especifica ninguno, se lee la entrada estándar. Cada línea se compara con la parte del patrón de cada declaración de acción de patrón. La acción asociada se realiza para cada patrón coincidente. Una línea de entrada está formada por campos separados por espacios en blanco. $1, $2.. definen los campos. $0 se refiere a la línea completa. Una declaración de acción de patrón tiene la forma: patrón {acción} Una acción faltante significa imprimir la línea; un patrón faltante siempre genera una coincidencia. Una declaración puede ser una de las siguientes: if (declaración condicional) [else declaración] while (declaración condicional) for (expresión;condicional;expresión) declaración break continue {[declaración]...} variable=expresión print [lista-de-expresiones] [>expresión] printf format [,lista-de-expresiones][>expresión] next # omitir el patrón restante en esta línea de entrada exit # omitir el resto de la entrada Las declaraciones terminan con ; (punto y coma), nuevas líneas (Ret) o llaves derechas. Veamos la sintaxis de awk de una manera un poco más simple. awk 'comandos' [nombre-archivo] Un programa awk (comandos) consta de un patrón opcional para hacer coincidir y una acción para realizar si se encuentra una coincidencia en la línea actual. Esta sintaxis se ve así: awk '/pattern/{action}' [filename] El patrón utilizado es una expresión regular entre barras diagonales. Si no se incluye ningún patrón, la acción se realizará para cada línea. Una acción puede contener varios comandos. Puede haber múltiples patrones y acciones. awk '/pattern1/{action1} /pattern2/{action2}' [filename} Uno de los comandos de awk es print. Pone la línea actual en la salida estándar. Sesión de Ejemplo: +---------------------------------------------------------------+ | $ awk '{print}' phone.lis | | Smith, Joan 7-7989 | | Adams, Fran 2-3876 | | StClair, Fred 4-6122 | | Jones, Ted 1-3745 | | Stair, Rich 5-5972 | | Benson, Sam 4-5587 | | $ | +---------------------------------------------------------------+ El awk divide cada línea de entrada en espacios en blanco y lleva un registro de la cantidad de campos en cada línea y cuenta la cantidad de líneas leídas. Cada campo se identifica por su número de campo y un $. $1 Identifica el primer campo $2 Identifica el segundo campo . $0 Identifica la línea completa NF Identifica la cantidad de campos en la línea NR Identifica la cantidad de líneas que se han leído Sesión de Ejemplo: +---------------------------------------------------------------+ | $ awk '{print NR,$1}' phone.lis | | 1 Smith, | | 2 Adams, | | 3 StClair, | | 4 Jones, | | 5 Stair, | | 6 Benson, | | $ | +---------------------------------------------------------------+ Para cambiar el orden de los nombres en phone.lis, utilice awk. La coma en el comando print le indica a awk que separe cada campo con un espacio. Sin la coma, la salida no tendría espacios. Sesión de Ejemplo: +---------------------------------------------------------------+ | $ awk '{print $2, $1 ""$3}' phone.lis | | Joan Smith, 7-7989 | | Fran Adams, 2-3876 | | Fred StClair, 4-6122 | | Ted Jones, 1-3745 | | Rich Stair, 5-5972 | | Sam Benson, 4-5587 | | $ | +---------------------------------------------------------------+ sort: ORDENAR UN FICHERO La utilidad sort ordena las líneas de todos los ficheros llamados juntos y escribe el resultado en una salida estándar. La entrada estandar se usa si - es usada como un nombre de fichero o no se especifican ficheros de entrada. Las comparaciones se basan en una o más claves de ordenación extraídas de cada línea de entrada. Solo hay una clave predeterminada, que es la línea completa, y el orden es lexicográfico por bytes en la secuencia de clasificación de la máquina. +===============================================================+ | Command format: sort [-cmu][-ooutput][-ykmem][-zrecsz] | | [-dfiMnr][-btx][+pos][-pos2][files] | | | | See on-line manual for options etc. | +===============================================================+ La forma más sencilla de utilizar la ordenación es añadirla al final de una secuencia de comandos. ¿Qué logra la siguiente línea de comandos? Sesión de Ejemplo: +---------------------------------------------------------------+ | $ grep '[45]' phone.lis | sed 's//73/' | sort| | Benson, Sam 734-5587 | | StClair, Fred 734-6122 | | Stair, Rich 735-5972 | | $ | +---------------------------------------------------------------+ El comando grep seleccionará solo aquellos registros que tengan un 4 de un 5 en el número de teléfono, esos registros se envían a sed que agregará "73" justo después del carácter de tabulación, luego los registros se envían a sort y se colocan en orden alfabético. Observe que hay un problema aquí, ¿StClair debería ir antes que Stair en una lista alfabética? La respuesta es NO. ¿Por qué sucedió esto? Ocurrió debido a la secuencia de intercalación para el ordenamiento predeterminado. Esto se puede solucionar especificando algunas opciones en la llamada a la utilidad de ordenamiento. Aquí hay algunas opciones para sort. Veamos si podemos determinar cómo solucionar el problema descubierto en el ordenamiento predeterminado. Opciones de ordenamiento: -f Convertir minúsculas en mayúsculas -r Invertir el ordenamiento de mayor a menor -b Ignorar los espacios en blanco iniciales -d Ordenamiento por diccionario: ignorar caracteres no alfanuméricos -m Fusionar dos archivos ordenados -n Ordenar la lista como números, no como caracteres numéricos Observe que la opción -f convierte minúsculas en mayúsculas. Esta opción hará que la clasificación de nuestro problema funcione correctamente. Sesión de Ejemplo: +---------------------------------------------------------------+ | $ grep '[45]' phone.lis|sed 's//73/'|sort -f | | Benson, Sam 734-5587 | | Stair, Rich 735-5972 | | StClair, Fred 734-6122 | | $ | +---------------------------------------------------------------+ También se puede ordenar la clasificación para que utilice solo una parte de la línea como clave de clasificación en lugar de la línea completa. La utilidad dividirá automáticamente cada línea en campos con delimitadores de espacios en blanco. Puede utilizar un carácter distinto de un espacio en blanco utilizando la opción -t. Los campos se configuran de la siguiente manera: 0 1 2 /----|/---|/-------------| Adams, Fran 2-3876 Para ordenar por el segundo campo, aquí está el comando de ordenación a ingresar. Sesión de Ejemplo: +---------------------------------------------------------------+ | $sort +1 phone.lis | | Adams, Fran 2-3876 | | StClair, Fred 4-6122 | | Smith, Joan 7-7989 | | Stair, Rich 5-5972 | | Benson, Sam 4-5587 | | Jones, Ted 1-3745 | | $ | +---------------------------------------------------------------+ A continuación se muestra una muestra de una clasificación en el tercer campo. Sesión de Ejemplo: +---------------------------------------------------------------+ | $sort +2 phone.lis | | Jones, Ted 1-3745 | | Adams, Fran 2-3876 | | Benson, Sam 4-5587 | | StClair, Fred 4-6122 | | Stair, Rich 5-5972 | | Smith, Joan 7-7989 | | $ | +---------------------------------------------------------------+ También se puede realizar una ordenación por la posición de un carácter dentro de un campo. Sesión de Ejemplo: +---------------------------------------------------------------+ | $sort +2.4 phone.lis | | StClair, Fred 4-6122 | | Benson, Sam 4-5587 | | Jones, Ted 1-3745 | | Adams, Fran 2-3876 | | Stair, Rich 5-5972 | | Smith, Joan 7-7989 | | $ | +---------------------------------------------------------------+ NOTA: El primer carácter de un campo es el delimitador de ese campo. 5.1 ARCHIVADOR Y MANTENEDOR DE BIBLIOTECA Este comando mantendrá grupos de archivos combinados en un único archivo comprimido. El uso principal de ar es crear y actualizar archivos de biblioteca que utiliza el editor de enlaces. También se puede utilizar para cualquier otro propósito similar. El encabezado del archivo consta de caracteres ASCII imprimibles. Si el archivo comprimido consta de caracteres imprimibles, entonces todo el archivo también es imprimible. +===============================================================+ | Command Format: ar key [posname] afile [name]... | | | | Unlike command options, the command key is required. The key,| | usually a - sign, is formed with one of the following letters | | drqtpmx. Arguments to the key are made from one or more of | | the following set, vuaibcis. See Appendix I for a complete | | list of command keys. | | | | posname is an archive member name used as a reference for | | positioning other files in the archive. | | | | afile is the name of the archive. | | | | name[s] are the constituent files in the archive. | +===============================================================+ Para ilustrar cómo crear y utilizar un archivo de almacenamiento, utilizaremos el programa en "C" llamado main.c y las dos funciones, funct1.c y funct2.c. Primero, crearemos los archivos de objeto que deseamos colocar en el archivo de almacenamiento. Sesión de Ejemplo: +---------------------------------------------------------------+ | $ cc -c main.c funct1.c funct2.c | | main.c: | | funct1.c: | | funct2.c: | | $ls -C *.o | | funct1.o funct2.o main.o | | $ | +---------------------------------------------------------------+ Recuerde que la opción -c no producirá un módulo ejecutable, pero sí creará los módulos de objeto. Estos módulos de objeto son archivos que colocaremos en un archivo. 5.2 Creación de un archivo de archivo con módulos de objeto En esta llamada a ar, utilizaremos la tecla de comando r que reemplazará los archivos nombrados en el archivo. La opción v dará una descripción detallada, archivo por archivo, de la creación del nuevo archivo de archivo. Sesión de Ejemplo: +---------------------------------------------------------------+ | $ ar rv functs.a funct1.o funct2.o | | a - funct1.o | | a - funct2.o | | ar: creating functs.a | | $ | +---------------------------------------------------------------+ El nombre del nuevo archivo de almacenamiento es functs.a. Los archivos que se han añadido a ese archivo son funct1.o y funct2.o. Las protecciones de archivo para el nuevo archivo de almacenamiento son rw-r--r--. 5.3 Verificación del contenido del archivo de almacenamiento El comando clave para listar la tabla de contenidos es t. El comando t imprimirá una tabla de contenidos del archivo de almacenamiento. Cuando se utiliza la opción v con el comando t, se obtendrá una lista larga de toda la información sobre los archivos. Sesión de Ejemplo: +---------------------------------------------------------------+ | $ ar tv functs.a | | rw-r--r-- 115/ 200 448 Sep 27 09:56 1990 funct1.o | | rw-r--r-- 115/ 200 448 Sep 27 09:56 1990 funct2.o | | $ | +---------------------------------------------------------------+ Esta salida muestra que hay dos miembros en este archivo de almacenamiento, a saber, funct1.o y funct2.o. Las protecciones de estos archivos son: propietario: lectura y escritura grupo: lectura otro: lectura Los campos son, de izquierda a derecha, las protecciones del archivo, propietario, grupo, tamaño (en bytes), fecha y hora de creación y, finalmente, el nombre del constituyente. 5.4 Eliminación de archivos de objetos duplicados Una vez que se ha creado y verificado el archivo, se pueden eliminar los archivos de objetos en su directorio. Esto se puede lograr con el comando rm. Sesión de Ejemplo: +---------------------------------------------------------------+ | $ rm funct?.o | | $ | +---------------------------------------------------------------+ El signo de interrogación (?) es un comodín que representa cualquier carácter individual. Los archivos funct1.o y funct2.o ya no existen en su subdirectorio. 5.5 Compilación de archivos principales y de archivo Ahora que los archivos de objeto, funct1.o y funct2.o, están en el archivo de archivo functs.a, puede vincularlos con main.o de la siguiente manera. Sesión de Ejemplo: +---------------------------------------------------------------+ | $ cc -o new_hello main.o functs.a | | $ ls -la new_hello | | -rwxr-xr-x 1 teacher class 17570 Sep 27 12:58 new_hello | | $ | +---------------------------------------------------------------+ Trabajo Práctico Número 5 Este trabajo práctico reforzará su comprensión de las ideas presentadas en este capítulo. Inicie sesión con el nombre de usuario y la contraseña que le proporcionó el instructor. Cada estudiante debe completar todo el taller. EJERCICIOS DE ESCRITORIO 1. ¿Qué hace la utilidad UNIX grep? 2. ¿Qué representan las siguientes expresiones regulares? ^Ba .* BB* J* [0-9]*$ 3. ¿Qué hace la utilidad UNIX sed? 4. ¿Qué hace la utilidad UNIX awk? 5. ¿Qué hace la utilidad UNIX sort? 6. ¿Cuál es el uso principal de la utilidad UNIX ar? EJERCICIOS DE COMPUTADORA Utilice el archivo de base de datos phone.lis para responder las siguientes preguntas. 7. "Quiero encontrar todos los números de teléfono que comiencen con 4 y terminen con 2" 8. "No recuerdo el nombre, pero creo que el apellido comienza con S y el nombre con F" 9. Encuentra a todas las personas con nombres de 3 caracteres. 10. Escribe un comando grep que encuentre todos los números de teléfono que no comiencen con 4, 5 o 6. 11. Escribe un comando grep que encuentre todas las entradas que comiencen con J-Z y terminen con 2 o 5. 12. Coloca un 23 delante de cada número de teléfono. (Pista: sed) 13. Reemplaza el nombre con la inicial del nombre de la persona y un punto. 14. Tarea: Se ha instalado un nuevo sistema telefónico y las personas con extensiones telefónicas que comienzan con 4 o 5 ahora tienen un nuevo prefijo: 73. Crea un archivo solo con las personas con los nuevos números de teléfono. 15. Imprime la lista de teléfonos mostrando el apellido y el nombre en el siguiente formato y ordenados por apellido. Nombre Apellido ¿No le parece ya suficiente?