lunes, 5 de julio de 2010

info eleven

Ejecutar PROCESOS en PRIMER y SEGUNDO PLANO

cuando emplea un comando para ejecutar un programa, el intérprete de comandos espera casi siempre a que el programa termine antes de pedirle que use otro comando. Sin embargo, podría ejecutar el comando para arrancar el programa, esperar a que éste comenzase y después pasar al comando siguiente de inmediato. Para lograr esto, se teclea un carácter “&” al final del comando.

Ejecutar el comando: ls>temp&, hará que el comando ls se ejecute en el PLANO SECUNDARIO y que la salida estándar se redireccione hacia un archivo llamado temp.

Cuando lanzamos un PROCESO en SEGUNDO PLANO obtenemos un PID y un número de trabajo. El PID, como ya hemos mencionado, es el número de PROCESO y es el método que utiliza el sistema operativo para identificar de forma única al PROCESO. En cambio el número de trabajo es un identificador de uno o varios procesos correspondientes a un usuario.

+ detiene (suspende) un PROCESO y lo deja en SEGUNDO PLANO.

La orden fg se utiliza para traer a PRIMER PLANO un trabajo que está en SEGUNDO PLANO, bien esté activo o bien esté detenido.

La orden fg se usa como: fg [%num_trabajo].

La orden bg se utiliza para poner en ejecución en segundo plano un trabajo que está en segundo plano detenido y se utiliza como:

bg [%num_trabajo].

Con la orden jobs podemos obtener una lista de los trabajos que hemos “lanzado” en el sistema.

La orden nohup lanza un proceso y lo independiza del terminal que estamos usando.

Los PROCESOS se organizan de forma jerárquica, de forma que si abandonamos la SHELL que nos conectó al sistema (abandonamos la sesión de trabajo) automáticamente se matarán todos los PROCESOS que dependan de ella.

El rango de prioridades va de -20 a 19, siendo -20 la PRIORIDAD máxima.
Cambiar prioridad a los PROCESOS

Por defecto, la PRIORIDAD con que se ejecutan los PROCESOS es 0.

Para “lanzar” un PROCESO con una determinada PRIORIDAD utilizamos el comando nice. Si queremos cambiar la PRIORIDAD de un PROCESO en ejecución utilizaremos el comando renice.

Archivos de registros con AWK

Podemos considerar que cada línea de un archivo es un “registro”, que cada uno de estos “registros” se compone de varios “campos” delimitados (o separados) por algún caracter delimitador, como por ejemplo un “*”, “:”, “#”, etc.

AWK usa $0 para identificar la línea completa del archivo (registro), $1 para el primer campo, $2 para el segundo campo..etc…

RS – Separador de registros (Record Separator), contiene el carácter que indica a AWK en qué punto del archivo acaba un registro y empieza el siguiente. Es “\n” por omisión.

NF – Número de campos de un registro (Number of Fields), contiene el número total de campos que contiene el registro que se está leyendo en cada momento. También se usa para nombrar el último campo.

NR – contiene el número de orden del registro que se está procesando en cada momento (Number of Record).

Para imprimir las líneas o registros del archivo arch, incluido el número del registro, usaremos: awk –F # ′{print NR”\t”$0}′ arch.

Para imprimir en pantalla los campos 1 y 2 del archivo arch separados por un caracter de tabulación (\t), usaremos: awk –F # -v OFS=“\t” ′{print $1,$2}′ arch.

Para imprimir las líneas impares del archivo arch, usaremos: awk ′{if (NR%2==1) print NR,$0}′ arch.

Para imprimir las líneas o registros del archivo /etc/passwd, usaremos: awk -F : ′{print $0}′ /etc/passwd.

Para mostrar solo los registros de usuarios del sistema en el archivo /etc/passwd, usaremos: awk -F : ′$3>=500 {print $0}′ /etc/passwd.

Para imprimir en pantalla un listado de todos los subdirectorios del directorio actual, usaremos: ls -l ¦ awk ′/^d/ {print $1,” “,$9}′.

Para mostrar los nombres de login de todos los usuarios “logueados” en la máquina, usaremos: who ¦ awk '{print $1}‘.

Para borrar sólo los archivos del directorio actual, usaremos: ls -l * ¦ grep -v drwx ¦ awk '{print "rm "$9}' ¦ bash.

Para borrar sólo los archivos del directorio actual, ahora sin usar grep: ls -l ¦ awk '$1!~/^drwx/ {print $9}' ¦ xargs rm.

info twelve

Procesamiento de registros con AWK

Estas construcciones presentan la siguiente sintaxis:

BEGIN {sentencias}  Preprocesamiento
{sentencias}  Procesamiento
END {sentencias}  Postprocesamiento

un ejemplo, el sencillo script “suma.awk” pone a cero la variable “total” antes de iniciar el proceso del archivo de entrada, añade a esa variable el valor correspondiente al contenido del primer campo de cada registro, y muestra el valor de la variable al final:

BEGIN {total=0}
{total += $1}
END {print “Total=“,total}

Para ejecutarlo podríamos usar:

[alumno@localhost ~]$ echo -e "10\n10\n10\n70" ¦ awk -f ./suma.awk
Total=100

Para contar y desplegar en pantalla la cantidad de líneas y palabras de un archivo arch, usaremos el script AWK “contar.awk”:

BEGIN {lines=0; words=0}
{
lines++;
words += NF;
}
END {print “Líneas=“,lines,” Palabras=“,words}

Para ejecutarlo podríamos usar:

[alumno@localhost ~]$ awk -f ./contar.awk arch
Líneas=3 Palabras=12




Veamos algunos ejemplos de uso de EXPRESIONES REGULARES en AWK:
Para obtener el tamaño promedio de los archivos del directorio actual, podemos usar:

ls -al ¦ awk ′BEGIN {total=0;count=0}
/^[^d]/ {total += $5; count++}
END {print total/count}′

Notar que la expresión regular o patrón es /^[^d]/ donde el primer ^ indica “coincidencia al principio de la línea” y el [^d] indica “cualquier cosa que no sea una d”.

Variables y datos en PERL
Las cadenas de caracteres se especifican literalmente por medio de un sucesión de caracteres delimitada por comillas ("..") o apóstrofes ('..').
Estas dos representaciones se distinguen por la interpretación hecha por PERL de las cadenas de caracteres. Cuando van delimitadas por comillas (".."), toda variable referenciada en el interior de la cadena se evalúa y se reemplaza por su valor.

Una lista es una colección ordenada de escalares; una variable que almacena una lista se llama array o arreglo.
Un hash, o memoria asociativa, es un mapeo de strings a escalares; los strings se llaman claves y los escalares valores.
Por ejemplo, para definir variables escalares podemos usar:

$num=10;
$hexa=0x1A;
$msg=“Hola Mundo!”

Una lista se define listando sus elementos, separados por comas y rodeados por paréntesis donde así sea requerido por la precedencia de los operadores.
Para definir una lista podemos usar:

@lista= (7, 15, “hola”, “chao”);

Los elementos individuales de una lista son accedidos utilizando un índice numérico (que inicia en 0), dentro de corchetes.
Por ejemplo, a $lista[0] le corresponde el 7, a $lista[1] le corresponde el 15, a $lista[2] le corresponde “hola” y a $lista[3] le corresponde “chao”.

Arreglos en PERL
Los arreglos o lista de PERL comienzan con el signo “@“ y contienen una lista de valores escalares (números y/o textos).
Al ser una lista de valores, para acceder a cada de uno estos se utiliza un número que indica su posición dentro de la lista.
La numeración empieza en 0, y se coloca entre corchetes [ ].

A este número que indica la posición de un valor dentro de la lista del arreglo se le denomina índice.
Como se vio anteriormente, para la asignación de un arreglo se usa el caracter “@”, y para acceder a un valor individualmente se utiliza el signo “$”, ya que en definitiva un arreglo está formado por distintas variables escalares.
Veamos un programa PERL que usa arreglos:

clear;
@A=(7,15,”hola”,”chao”);
print $A[1],”\n”;

Si este programa tiene como nombre “prg1”, para ejecutarlo usaríamos:

[alumno@localhost ~]$ perl prg1
15
[alumno@localhost ~]$

Asociados a los arreglos, existen algunas funciones en PERL que ayudan a poner o sacar elementos de la lista de datos del arreglo:
push – Colocar nuevos elementos al final de la lista: push(@arreglo, valores).
pop – Sacar el último elemento del arreglo. Se puede asignar a una variable tipo escalar: $variable=pop(@arreglo).

unshift - Reemplazar el primer elemento del arreglo: unshift(@arreglo, valor).
shift - Sacar el primer elemento del arreglo. Se puede asignar a una variable de tipo escalar: $variable=shift(@arreglo).
También se tiene una notación especial para conocer el último índice del arreglo, por medio de $#nombre_arreglo.

Veamos un ejemplo en donde se muestran los efectos de la aplicación de estas funciones sobre un arreglo.
Para efectos de comprensión se han especificado los valores impresos por los print y se han “dibujado” los arreglos y sus contenidos, en la medida que se aplican las funciones sobre él.

clear;
@A=(7,15,”hola”,”chao”); - - - - - -
print $A[1],”\n”;  15
push(@A,10,”Perl”); - - - - - - - - - -
print $A[5],”\n”;  Perl
print “Último Índice=”,$#A,”\n”;  5
shift (@A); - - - - - - - - - - - - - - - - -
print $A[0],”\n”;  15

Entrada/Salida en PERL
El print es la instrucción básica para mostrar el valor de las variables en pantalla.
Existen muchos modificadores para la salida de los valores de las variables en pantalla, entre algunos de estos, podemos nombrar: “\n” para nueva línea, “\t” para tabulación, “\r” para retorno de carro, xN para repetir un caracter o texto anterior N veces, etc.
Veamos algunos ejemplos de uso de print:

print “hola PERL \n”;  hola PERL
print “5x3”;  555 (muestra 3 veces el 5)
print “hola”x2;  hola hola

Para asignar un valor desde el teclado a una variable, se asigna a la variable la representación del teclado , de acuerdo con el siguiente formato:

$variable=;

Por ejemplo, veamos un simple programa PERL con E/S:

clear;
print “Ingrese Nombre: “;
$nom=;
print “Nombre=$nom”;

La función chop se utiliza para eliminar el último caracter de una entrada de datos, normalmente nueva línea.
chop(...) elimina el último caracter de una entrada por teclado. Un ejemplo de uso sería: $nom=chop($nom);.

Control del flujo en PERL
La mayoría de las estructuras de control en PERL, han sido heredadas del lenguaje C/C++.
La estructura condicional más simple es el IF:

if (condición){
sentencias…
}
else{
sentencias…
}

En la evaluación de las condiciones del IF (y de cualquier sentencia de control del flujo) podemos usar <, <=, >, >=, == y != para comparar números y lt, le, gt, ge, eq y ne para comparar literales.
Veamos un ejemplo de uso de estos operadores:

clear;
print “Número: “;
$num=;
chop($num);
if ($num >= 0){
print $num,” es positivo \n”;
}
else{
print $num,” es negativo\n”;
}

La sentencia iterativa WHILE presenta el siguiente formato:

while (condición){
sentencias…
}

Veamos un ejemplo de uso de la sentencia WHILE:

clear;
$i=1;
while ($i <= 5){
print $i*$i,”\n”;
$i=$i + 1;
}

La sentencia FOREACH se utiliza comúnmente para recorrer los valores de los arreglos o listas. Los elementos del arreglo o lista actúan como contadores del ciclo, ejecutándose el ciclo una vez por cada uno de estos elementos. La sintaxis para FOREACH es la siguiente:

foreach $variable (lista){
sentencias…
}

#Llenar arreglo con datos clear; @A=(); while (1){ print “Ingrese dato: “; $dato=;
chop($dato);
push(@A,$dato);
print “Más datos [Si/No]: “;
$opc=;
if ( chop($opc) eq “No”){
last;
}
}

#Listar los datos del arreglo
clear;
print “Listado de datos \n\n”;
foreach $a (@A){
print $a,”\n”;
}

#Mostrar cantidad de datos
print “Cantidad de datos=“,$#A+1,”\n”;

#Sumar los datos del arreglo
clear;
$sum=0;
foreach $a (@A){
$sum = $sum + $a;
}
print “Suma=“,$sum,”\n”;

Veamos un ejemplo de uso de la sentencia FOREACH:

clear;
@A=(1,7,”Hola”,10);
foreach $a (@A){
print $a,”\n”;

info ten

Cuando se ejecuta en modo debug syslogd no libera el terminal. Después de desplegar la tabla con el resumen de acciones queda desplegando en pantalla cada mensaje que recibe y las acciones que se le aplican.

El comando logger permite enviar eventos al demonio syslogd, por lo que se utiliza en scripts para registrar mensajes vía sysklogd. Por ejemplo, si hacemos:

# logger -t mi_programa -f /var/log/messages "Mensaje ejemplo"

veremos que se ha añadido a /var/log/messages la línea:

May 14 23:10:13 pc450 mi_programa: Mensaje ejemplo

Para acceder a esta información podemos utilizar el comando who (también se puede utilizar el comando last).

/var/log/lastlog: Este archivo contiene información relativa a la fecha y hora del último login de cada usuario, para acceder a esta información podemos hacerlo con el comando lastlog.

Para indicar de que usuario queremos saber, anteponemos -u al nombre de usuario, por ejemplo, podemos usar: lastlog -u alumno.

/var/log/faillog: este log registra los intentos fallidos de cada usuario al querer “logearse” en el sistema, para acceder tenemos el comando faillog.

[alumno@localhost ~]$ faillog –u alumno
Username Failures Maximum Latest alumno 0 2

En la columna "Maximum" se indica la cantidad de intentos erróneos que se permiten antes de deshabilitar la cuenta, para modificar este valor se debe usar la orden faillog -u alumno -m valor donde valor es el número máximo.

Seguridad general de los logs

Para dejar un archivo en modo sólo-añadir, se puede utilizar el siguiente comando:

[root@localhost ~]# chattr +a nombre_archivo

A la función chattr sólo tiene acceso el superusuario.

Si se dejan todos los archivos en modo sólo-añadir, hay que tener en cuenta que fallarán los programas de rotación de logs, puesto que no pueden dejar en cero el archivo de log. Para deshabilitar el atributo sólo-añadir se agrega la siguiente línea al script:

chats -a nombre_archivo

Si los archivos de logs se dejan en el sistema, quizás sea preferible activar también el flag de inmutables, de forma que no se puedan falsificar con facilidad.
Para activar el archivo como inmutable, simplemente utilizar el comando:

[root@localhost ~]# chattr +i nombre_archivo

lo que evitará cualquier cambio en el archivo.
sólo el usuario root tiene acceso al flag de inmutable.

La idea más generalmente aceptada acerca de un PROCESO es la de programa en ejecución.

Proceso:=Programa en ejecución

En WINDOWS a los procesos se les denomina TAREAS, en otros sistemas operativos se les denomina TRABAJOS o JOBS.

Los PROCESOS son entidades activas (se están ejecutando) y los programas son entidades pasivas (NO se están ejecutando, NO tienen actividad), de aquí que:

Proceso≠Programa

Información de los PROCESOS

[root@localhost ~]$ ps
PID TTY TIME CMD
8621 pts0 00:00:00 -bash
8745 pts0 00:00:00 ps
[root@localhost ~]$

Como se puede ver el primer número es el PID que el kernel del sistema le asigna al PROCESO y en la columna CMD se puede ver el nombre del PROCESO.

TTY identifica la terminal o consola donde se está ejecutando el PROCESO. La columna TIME nos indica la cantidad de tiempo total que el PROCESO se ha estado ejecutando.
Al ser un comando estándar en todos los UNIX y LINUX, ps soporta una buena cantidad de parámetros y opciones especificadas en versiones anteriores del comando.

El parámetro -e devuelve un listado de todos los procesos que se están ejecutando.
El parámetro -f devuelve un listado extendido. En este último caso veremos en pantalla el PPID del proceso (identificador del proceso padre) y la hora en la que se ejecutó el proceso (STIME).

Los parámetros pueden aparecer juntos en el mismo comando, es decir, podríamos llamar al comando ps de la siguiente forma: ps –ef, de esta manera obtendríamos un listado extendido de todos los procesos que se están ejecutando en el sistema.
El parámetro -u lista información de los procesos lanzados por un determinado usuario, así, ps -u alumno, listará información de los procesos que está ejecutando el usuario alumno.

Matar/Terminar PROCESOS en LINUX

Hay dos formas básicas de terminar procesos:

kill
kill -9

En resumen, hay un total de 32 señales que se pueden enviar a los procesos, sin embargo, las más utilizadas son las siguientes:

kill -1 (SIGHUP) para reiniciar un proceso.
kill -9 (SIGKILL) para matar un proceso.
kill -15 (SIGTERM) para terminar un proceso.

Ejemplo funciones en BASH

#!/bin/bash
#función para listar el directorio
function Listar(){
if test –d $1
then
ls –l $1
fi
}
#PRINCIPAL
clear
echo –e “Ingresar un Directorio: \c”
read dir
Listar $dir #Llamada a la función Listar


#!/bin/bash
function Salir(){
exit
}
function Saludo(){
echo –e “HI!!!…\n”
}
#PRINCIPAL
clear
Saludo #Llamada a la función Saludo
Salir #Llamada a la función Salir


Las funciones en BASH pueden “retornar” un valor por medio de la sentencia return, que se usa de la misma manera que exit.
La sentencia return solo sirve para retornar enteros entre 0 y 255.

un ejemplo de FUNCIÓN que retorna un valor:

#!/bin/bash
function suma(){
c=$(expr $1 + $2)
return $c
}

#PRINCIPAL
suma 100 150
echo –e “suma=$?\n”

definir funciones en la línea de ordenes, de la siguiente manera:

[root@localhost ~]$ function saludo(){
> echo hi
>}
[root@localhost ~]$ function salir(){
> exit
>}
[root@localhost ~]$ declare –f
declare –f salir
declare –f saludo

Los PARÁMETROS POSICIONALES son los encargados de recibir los argumentos de un SCRIPT y los PARÁMETROS DE UNA FUNCIÓN.
Los nombres de los PARÁMETROS POSICIONALES son 1, 2, 3, etc. por lo que para acceder a ellos utilizaremos $1, $2, $3, etc.

#!/bin/bash
function impParam(){
echo –e “Nombre del SCRIPT : $0”
echo –e “Primer parámetro : $1”
echo –e “Segundo parámetro : $2”
echo –e “TODOS los parámetros : $*”
}

#PRINCIPAL
clear
impParam hola a todo el mundo

Variables locales y globales

Por defecto, los PARÁMETROS POSICIONALES son locales al SCRIPT o FUNCIÓN y no se pueden acceder o modificar desde otra FUNCIÓN.

A diferencia de los PARÁMETROS POSICIONALES, el resto de variables que definimos en un SCRIPT o FUNCIÓN son globales, es decir, una vez definidas en el SCRIPT son accesibles (y modificables) desde cualquier FUNCIÓN.

#!/bin/bash
function impParam(){
echo –e “Nombre del SCRIPT : $0”
echo –e “Primer parámetro : $1”
echo –e “TODOS los parámetros : $*”
}

#PRINCIPAL
clear
impParam hi everyone
$1=hola


Librería de FUNCIONES

A la hora de programar SCRIPTS de SHELL no es que existan herramientas para declarar librerías, pero se pueden simular de cierta manera colocando el código de FUNCIONES en archivos de SCRIPTS separados.

El siguiente ejemplo corresponde a un ejemplo de uso de librerías, usando un archivo con las funciones que queremos “exportar”:

Se graban en el archivo librería.sh las FUNCIONES que se desean “exportar”.

[alumno@localhost ~]$ vi librería.sh
function saludar(){
echo –e “Hi\n”
}
function salir(){
exit
}

Se incluye el archivo librería.sh en el SCRIPT en donde deseemos ocupar las FUNCIONES “importadas”.

#!/bin/bash

#libreria.sh contiene las funciones a ser utilizadas
source librería.sh

Arreglos en BASH

En BASH las variables de tipo arreglo se declaran por medio de:

declare –a nombre_arreglo[tamaño]

En esta definición tamaño hace referencia a la cantidad de elementos del arreglo.

En BASH podemos asignar datos o valores a un arreglo de la siguiente forma:

nombre_arreglo[índice]=valor

En esta definición índice hace referencia a la posición que el valor ingresado tendrá dentro del arreglo.

En BASH es posible referenciar los datos del arreglo a través de la expresión:

${nombre_arreglo[índice]}

Es posible referenciar a TODOS los datos del arreglo de una sola vez por medio de la orden:

${nombre_arreglo[*]}

El total de elementos del arreglo se puede determinar usando:

${nombre_arreglo[@]}

Ejemplos de uso de arreglos en BASH

#Función para colocar datos en
#el arreglo
function LLenar_arreglo(){
local i=1
while test $i –le 5
do
echo –e “Numero: \c”
read A[$i]
i=$(expr $i + 1)
done
}


#Función para mostrar los datos
#del arreglo
function Mostrar_arreglo(){
local i=1
while test $i –le 5
do
echo –e “A[$i]=${A[$i]}\n”
i=$(expr $i + 1)
done
}



#PRINCIPAL
#!/bin/bash
clear
declare –a A[5]
LLenar_arreglo
Mostrar_arreglo

ejercicios 2 respuesta corta

Ejercicios AWK

-Quitar las líneas vacías de un archivo:

awk '!/^$/ {}' archivo

-Mostrar el login de los usuarios que están conectados:

w awk 'NR>2 {print $1}'

-Mostrar el login y el nombre completo de los usuarios cuyo login empieza y termina en ‘a’:

awk 'BEGIN {FS=":"} /^a[^:]*a:/ {print $1,$5}' /etc/passwd

-Borrar solo archivos (puede hacerse con rm nada más, pero qué pasa con alias como 'rm -r')

ls -l * grep -v drwx awk '{print "rm "$9}' sh

-Imprime sólo los nombres de usuarios del archivo /etc/passwd

awk –F: '{ print $1 }' /etc/passwd

-Imprimir todas las líneas del archivo con número de línea

awk '{ print NR $0 }'

-Escribir un comando AWK que cumpla la misma función que wc –l archivo:

awk 'END { print NR }' archivo

-Mostrar sólo los nombres y los tamaños de los archivos del directorio actual:

ls -l awk '{ print $8 ":" $5 }'

-Mostrar sólo los nombres y tamaños de archivos .txt:

# ls -l awk '$8 ~ /\.txt/ { print $8 ":" $5 }'

-Imprimir las líneas de un archivo que tengan más de 4 campos/columnas:

# awk 'NF > 4 {print}' archivo

-Imprimir el último campo de cada línea de un archivo:

awk '{ print $NF }' archivo

-Imprimir los campos de cada registro o línea de un archivo en orden inverso:

awk '{ for (i = NF; i > 0; --i) print $i }' fichero

-Imprimir última línea de un archivo:

awk '{line = $0} END {print line}' archivo

-Imprimir las primeras 10 líneas de un archivo:

awk 'NR < 10 {print}' archivo

-Mostrar todas las líneas de un archivo que contengan una determinada cadena

awk '/cadena/ { print }' archivo

-Mostrar todas las líneas de un archivo que NO contengan una determinada cadena

awk '! /cadena/ { print }' archivo

-Mostrar en pantalla los campos 1 y 3 del archivo /etc/passwd:

awk -F":" '{ print $1 "\t" $3 }' /etc/passwd

-Calcular la suma y el promedio de todas las primeras columnas del archivo:

awk '{ suma += $1 } END { print "suma:", s, " media:", s/NR }' archivo

-Imprimir los usuarios ordenados y su hora de conexión (primero este campo).

who awk '{print $5, $1}' sort

-Imprimir un número decimal reservando espacio para 4 dígitos (NR = número de línea
actual), un string ($0 = la línea completa), y salto de línea.

awk '{printf "%4d %s\n", NR, $0}' archivo

ejercicio awk

Las siguientes preguntas son relativas a un archivo de alumnos con el siguiente formato:
Nombre;Apellido;Código;Número
Por ejemplo, los datos de dicho archivo podrían ser:
Juan;Pérez;A-01;17
Manuel; Parra;B-05;24
Pablo;Díaz;A-03;45
Juan;Catrileo;A-01;34
Se trata que Ud. Elabore programas en AWK que realicen la acción que se le pide en los siguientes enunciados:
1.- Escribir un programa que permita listar los datos de todos aquellos alumnos que se encuentran en el curso con código “A-01”.




2.- Escribir un programa que permita obtener el promedio de todos los datos numéricos del archivo (el cuarto campo en el archivo).



3.- Escribir un programa que permita listar el nombre, apellido y código de todos los alumnos con apellido “Pérez”.



4.- Escribir un programa que permita obtener el promedio de todos los datos numéricos del archivo de aquellos alumnos con apellido “Pérez”.



5.- Escribir un programa que permita grabar en un archivo llamado Alumnos_A-01 todos los alumnos que se encuentren en el curso con código A-01.



6.- Escribir un programa que permita determinar el (o los) alumno (s) cuyo número sea el mayor en el archivo.



7.- Escribir un programa que permita listar la información (los cuatro campos) de todos aquellos alumnos cuyos nombres empiezan con “M”.

sumas en awk

# El siguiente ejemplo suma las columnas 2, 3 y 4 de un archivo, presentando el resultado al final.
cat archivo | awk '
BEGIN { campo1=0; campo2=0; campo3=0; }
{
campo1+=$2;
campo2+=$3;
campo3+=$4;
}
END { printf "campo1 = %d\t campo2 = %d\t campo3 = %d\n", campo1, campo2, campo3; }'

# En el siguiente ejemplo se hace lo mismo que en el anterior pero para las líneas que contengan
la palabra TOTAL en el primer campo.
cat archivo | awk 'BEGIN { campo1=0; campo2=0; campo3=0; } $1 ~ /TOTAL/ {
campo1+=$2;
campo2+=$3;
campo3+=$4;
}
END { printf "campo1 = %d\t campo2 = %d\t campo3 = %d\n", campo1, campo2, campo3; }'

awk introduccion

Introducción

El nombre awk proviene de las iniciales de sus desarrolladores : Alfred V. Aho, Brian W. Kerningan y Peter J. Weinberger, de los Laboratorios Bell de AT&T. Inicialmente se desarrolló para escribir programas muy cortos, pero las características de este atrajo a los usuarios de tal modo, que lo impulsó más allá de la idea original de los autores. En 1985 apareció una nueva versión llamada nawk, en la que se implementan características nuevas como son:

• Funciones de usuario.
• Expresiones regulares dinámicas con sustitución de texto.
• Mayor número de funciones intrínsecas y variables.
• Nuevos operadores y estamentos.
• Entrada de múltiples archivos.
• Acceso a argumentos en la línea de comandos.
• Mejora de los mensajes de error.

awk es un lenguaje de búsqueda y procesamiento de patrones. Esto quiere decir que awk es capaz de buscar un patrón dentro de un archivo (al igual que grep) y tratarlo según unas operaciones determinadas. Con awk se pueden desarrollar auténticos programas.

Según esto awk es capaz de procesar un archivo con datos organizados por columnas y generar nuevas columnas con los valores resultantes de realizar ciertos cálculos u operaciones.

A diferencia de comandos Unix como grep y sed, que filtran y procesan texto, awk incorpora su propio lenguaje de programación, siendo capaz de ofrecer operaciones aritméticas, relaciones lógicas y variables. Se pueden desarrollar programas con awk que procesen la entrada estándar o un archivo, realizando tareas como tratar archivos de texto como bases de datos. El lenguaje de programación awk incluye estamentos como for, while e if-else, así como un conjunto de funciones y variables incorporadas.

La sintaxis de awk es:

awk [-f archivo_programa] [-Fc] ['programa'] [variable=valor ...] [archivo]
donde:

archivo_programa : especifica el archivo fuente del programa a aplicar a archivo.
c : especifica el carácter delimitador de campos. Por defecto se considera el espacio en blanco.

programa : especifica el conjunto de patrones e instrucciones a ejecutar con archivo. La diferencia con archivo_programa, es que en este caso hay que especificar los patrones e instrucciones en la línea de comandos. Para evitar interferencias con la shell deben ir encerradas entre comillas simples (').

variable=valor : se utiliza para establecer los valores que tomarán las variables que utilice el programa.

archivo : archivo que será procesado por awk. Si se especifica "-" se interpretará como la entrada estándar.

Campos y Variables

Una línea de entrada se divide en campos separados por espacios, y cada campo se denomina como $1, $2, etc. $0 indica la línea entera. Estas variables se pueden manipular (sumar, cambiar, etc.) como cualquier otra varible, por ejemplo:
awk '{ $1 = $2 + $3; print $0 }' archivo
Sumará los campos 2 y 3 en el campo 1, e imprimirá el nuevo registro (la línea completa).

Se pueden referir a los campos con expresiones numéricas como $i, $(n+1), $(NF*3/NR), etc. Si la expresión resultante no es un entera, se truncará la parte decimal. El tratamiento de un campo como texto o numérico dependerá del contexto, awk resuelve las posibles ambigüedades tratando los campos como texto (por ejemplo cuando se compara un texto con un número), por ejemplo:

x=10 Asigna a x el valor numérico 10
x="Hola" Asigna a x la cadena Hola
x="2"+"2" Asigna a x el valor 4, como si se hubiera escrito x=2+2, debido a que el contexto demanda un valor numérico.

En los programas de awk no es necesario declarar las variables (indicar el tipo de variable de que se trata), se realizará automáticamente en función del contexto. Por defecto se inicializan a la cadena nula o valor numérico 0, por lo que no es necesario inicializarlas.

Existen unas variables predefinidas, que pueden ser utilizadas dentro del programa:


•FS : Separador del campo de entrada. Se puede especificar con la opción -Fc en la línea de comandos
•FILENAME : nombre del archivo de entrada actual
•RS : Separador de registro de entrada
•OFS : Separador del campo de salida.
•ORS : Separador de registro de salida
•NF : Número de campos en el registro actual
•NR : Número de registros procesados hasta el momento. Al final del programa se podrá conocer el número e registros tratados.
•RSTART : Posición de la cadena en la que se verifica el patrón utilizado, comenzando desde 1. Es equivalente al valor retornado por la función match.
•RLENGTH : Longitud de la cadena en la que se verifica el patrón utilizado.
•SUBSEP : Separador de cadenas en arrays multidimensionales. El valor por defecto es " 34".

Los valores de las variables relativas a separadores se pueden modificar en cualquier momento, asignándole el valor de cualquier carácter. Por defecto, los separadores de campos son espacios, y los de registros el carácter nueva línea.

Formato de los estamentos

La estructura general de los estamentos o conjuntos patrón-acción es:
Patrón { acción }

Interpretación:

•Para cada línea que verifique lo especificado en el patrón, se ejecutará la acción indicada.
•La acción siempre va encerrada entre llaves.
•Se pueden especificar varias acciones, separándolas por ";" o por el carácter nueva línea.

Si no se especifica la acción, se mostrarán por pantalla aquellas líneas que contengan el patrón. La acción está formada por estamentos (if, for, print, sprintf, next), los cuales deben finalizar en ";", Nueva Línea o llaves. Dentro de las acciones se pueden realizar operaciones matemáticas, de concatenación, etc. Las variables utilizadas pueden ser escalares, campos o tablas, y son inicializadas a la cadena nula.

Los patrones deben ir rodeados por caracteres "/", y puede contener dos patrones separados por una coma, en cuyo caso la acción se realizará para aquellas líneas comprendidas entre la primera aparición del primer patrón y la siguiente aparición del segundo patrón. Si se utiliza el símbolo "~", indicará que el patrón de la derecha está contenido en el campo de la izquierda, y si se utiliza "!~", indicará que no está contenido.

Existen dos etiquetas opcionales, con un significado especial, que hacen que un programa awk tenga una estructura como la siguiente:

BEGIN { acción }
Patrón { acción }
END { acción }

La acción indicada en la etiqueta BEGIN se ejecutará antes de leer cualquier entrada, mientras que la acción asociada a la etiqueta END se ejecutará una vez tratadas todas las entradas. La etiqueta END se puede utilizar para imprimir resultados totales, o cálculos realizados con todos los registros leídos.

Cuando el conjunto patrón-acción se introduce desde la línea de comandos, se recomienda que vaya encerrado entre comillas simples, para protegerlo de la shell.

Por ejemplo:

Desde un archivo Desde la shell de Unix
length > 60 awk 'length > 60'
A continuación se muestran los diferentes tipos de acciones y estamentos.
if (expresión) estamento [else estamento]
while (expresión) estamento
for (inicialización ; final ; incremento) estamento
for (var in array) estamento
Do estamento while (expresión)
break
continue
[ [estamento] }
expresión por ejemplo una asignacion var=valor
print [lista de expresiones] [ > expresión]
printf formato[, lista de expresiones] [ > expresión]
return [expresión]
next salta los elementos restantes de la línea de entrada
delete array [expresión] Borra un elemento array
exit [expresión] Finaliza la ejecución del programa, devolviendo el valor indicado en expresión.

Operaciones

Un programa awk puede hacer operaciones en coma flotante, utilizando los siguientes operadores:

+, -, *, / Adición, sustración, multiplicación y división
% Operador módulo o resto.
++, -- Operador de incremente y decremento
+=, -=, *=, /=, %= Asinación al estilo C (x += 1 equivale a x = x + 1)
O : exp.1 exp2 verdadera si es cualquiera de las dos ; exp. 2 no se evalua si expr1 es verdadera
&& Y : exp1 && exp2 verdadera si ambas lo son , expr2 no se avalúa si expr1 es falsa
> >= < <= == != Operaciones relacionales Nothing Concatenacion de cadenas Funciones Incorporadas Las siguientes funciones se pueden utilizar para la realización de operaciones aritméticas y con cadenas de caracteres. Función Descripción length(x) Devuelve la longitud del argumento sqrt(x) Devuelve la raíz cuadrada del argumento log(x) Devuelve el logaritmo en neperiano del argumento (en base e) exp(x) Devuelve el valor de e elevado al argumento int(x) Devuelve la parte entera del argumento cos(x) Devuelve el coseno del argumento sin(x) Devuelve el seno del argumento atan(x) Devuelve el arcotangente del argumento rand() Devuelve un número aleatorio comprendido entre 0 y 1 match(s,r) Devuelve la posición de s en donde ocurre r, comenzando desde 1. Si no existe devuelve 0. substr(s,m,n) Devuelve la subcadena de s que comienza en la posición m y finaliza en la n. sub(r,t,s) Sustituye la primera ocurrencia de t por r en la cadena s. Si no se especifica s se tomará todo el registro ($0). gsub(r,t,s) Igual que sub, pero sustituyendo todas las ocurrencias. split(s,array,sep) Divide la cadena s en array[1],...,array[n]. Se devuelve el número de elementos. Si no se especifica el separador en sep se utilizará el valor de FS. s puede ser una variable. index(s1,s2) Devuelve la posición de la cadena s1 en donde se encuentra la cadena s2. En caso de no encontrarse se devuelve 0. sprintf(f,e1,e2,...) Devuelve la cadena resultante de imprimir los valores e1, e2, ... con el formato especificado en f. toupper(s) Devuelve la cadena s convertida a mayúsculas. tolower(s) Devuelve la cadena s convertida a minúsculas. system(cmd) Ejecuta el comando UNIX cmd especificado y retorna el estado de salida de este. print e1, e2, ... Presenta en la salida los valores e1, e2, ... printf f, e1, e2, ... Presenta en la salida los valores e1, e2, ... con el formato especificado por f (al estilo C: %s, %d, etc.). close(f) Cierra el archivo o pipe abierto con print, printf o getline. getline X Lee el siguiente registro de la entrada y se lo asigna a X, si no se especifica X se asignará a $0. Funciones Las funciones se pueden definir (en la posición de un estamentopatrón-acción) del siguiente modo: function Nombre_Función(p1, p2, p3) { ..., return x } Los parámetros se pasan por valor si son escalares y por referencia si se pasa el nombre del array. Los parámetros son locales, mientras que el resto de las variables son globales. Las funciones pueden llamarse de forma recursiva. Ejemplos Ejemplos de patrones /prueba/ Todas las líneas que contengan la cadena "prueba". $2 ~ /prueba/ Todas las líneas cuyo segundo campo contenga la cadena "prueba". $1 !~ /prueba/ Todas las líneas cuyo primer campo no contenga la cadena "prueba". /start/ , /stop/ Imprime todas las líneas existentes entre los patrones start y stop. Ejemplos de acciones { print $5 } Imprime el campo 5. { print $1 $3 } Imprime los campos 1 y 3 consecutivamente. { s=$2+$3 ; print s } Suma los campos 2 y 3 e imprime el resultado. {tot=$2+$3; print $0, tot} Suma de los campos 2 y 3, e imprime la línea original y la suma. BEGIN {FS = ",[ \t]*[ \t]+" } { s += $1; print $2, $1 } END { print "La suma es ", s , "La media es ", s/NR Toma como separador de entrada la coma y/o los blancos y tabulaciones. Suma el primer campo de todos los registros e imprime los campos 2 y 1 (en ese orden). Al final imprime el total y la media. Ejemplos ls -l awk '/txt/ { print &8 }' - Muestra los archivos que contengan como propietario, nombre, grupo, etc. la cadena txt. El símbolo "-" indica que el archivo es la entrada estándar. awk '/cadena/ { cont=cont+$2 ; print $2 "\t" cont }' cont=0 archivo Busca cadena en archivo y en una variable llamada cont (contador) va sumando los valores del campo 2 e imprimiendo dicho campo, un tabulador y el valor del contador. Al final de la salida tendremos la suma total de los valores que ha tenido cadena en el campo 2. awk '$2>0 { print $1," ", $2 }' archivo Para cada línea de archivo, si el 2º campo es positivo, imprime los dos primeros campos.

awk '$2>0 { printf "%s %d\n", $1, $2 }' archivo Idem que el caso anterior, suponiendo que el primer campo es una cadena de caracteres.

awk '{gsub(" ","",$0); print $0;}' archivo Elimina todos los espacios en blanco del archivo especificado y lo muestra en pantalla.