En el programa awk típico, toda la entrada se lee de la entrada estándar (normalmente
el teclado) o de los fichero cuyos nombres se especifican en la línea de comando
de awk. Si especificas ficheros de entrada, awk lee los datos del primer fichero hasta que alcanza
el final del mismo; después lee el segundo fichero hasta que llega al final,
y así sucesivamente. El nombre del fichero de entrada actual puede ser conocido
por la variable implícita FILENAME (Ver la sección 12. Variables
Implícitas (Built-in).
La entrada se lee en unidades llamadas
registros, y éstos son procesados por las reglas uno a uno. Por defecto,
cada registro es una línea del fichero de entrada. Cada registro leído es dividido
automáticamente en campos, para que puedan ser tratado más fácilmente
por la regla. En raras ocasiones necesitarás usar el comando getline, el cual puede realizar entrada explícita de cualquier
número de ficheros (Ver la sección Entrada explícita con getline)
El lenguaje awk divide sus registros de entrada en campos. Los registros están separados
por un carácter llamado el separador de registros. Por defecto, el separador
de registros es el carácter newline. Por lo tanto, normalmente, un registro
se corresponde con una línea de texto. Algunas veces puedes necesitar un carácter
diferente para separar tus registros. Puedes usar un carácter diferente mediante
la llamada a la variable empotrada RS
(Record Separator).
El valor de RS es una cadena que dice como separar los registros; el
valor por defecto es \n, la cadena formada por un
único carácter newline. Esta es la razón por la cual un registro se corresponde,
por defecto, con una línea.
RS puede tener cualquier cadena como valor, pero solamente
el primer carácter de la cadena se usará como separador de registros. El resto
de caracteres de la cadena serán ignorados. RS es excepcional en este sentido; awk usa el valor completo del resto de sus variables implícitas.
Puedes cambiar el valor de RS en un programa awk con el operador asignación, = (Ver la sección Expresiones
de Asignación). El nuevo carácter separador
de registros de entrada debería estar entre comillas para que sea una constante
cadena. A menudo, el momento adecuado para hacer esto es el principio de la
ejecución, antes de procesar ninguna entrada, de modo que el primer registro
sea leído con el separador apropiado. Para hacer esto, use el patrón especial
BEGIN (Ver la sección Los Patrones Especiales BEGIN y END).
Por ejemplo:
awk 'BEGIN { RS = "/" } ; { print $0 }' ListaBBS
cambia el valor de RS a /, antes de leer ninguna entrada. Esta es una cadena cuyo primer carácter es una barra; como resultado, los registros se separarán por las barras. Después se lee el fichero de entrada, y la segunda regla en el programa awk (la acción sin patrón) imprime cada registro. Debido a que cada sentencia print añade un salto de línea al final de su salida, el efecto de este programa awk es copiar la entrada con cada carácter barra cambiado por un salto de línea. Otra forma de cambiar el separador de registros es en la línea de comandos, usando la característica asignación de variable (Ver la sección 14. Invocación de awk).
awk '...' RS="/" sourcefile
Esto fija el valor de RS a /, antes de procesar sourcefile.
La cadena vacía (una cadena sin caracteres) tiene
un significado especial como valor de RS: significa que los registros están separados solamente
por líneas en blanco. Ver la sección Registros de múltiples líneas,
para más detalles.
La utilidad awk guarda el número de registros que han sido leídos hasta
el momento del fichero de entrada actual. Este valor es almacenado en la variable
implícita llamada FNR. Esta variable es inicializada
a cero cuando se cambia de fichero. Otra variable implícita, NR, es el número total de registros de entrada leídos de todos los ficheros.
Comienza en cero pero nunca es automáticamente reseteada a cero.
Si cambias el valor de RS a mitad de la ejecución de un programa awk, el nuevo valor se usa para delimitar los registros
siguientes, pero el registro que esta siendo procesado en ese momento (y los
registros ya leídos) no se ven afectados.
Cuando awk lee un registro de entrada, el registro es automáticamente
separado o particionado por el intérprete en piezas llamadas campos.
Por defecto, los campos son separados por espacios en blanco, al igual que las
palabras de una frase. Los espacios en awk significan cualquier cadena de uno o más espacios y/o tabuladores; otros
caracteres tales como newline, formfeed, etc … que son considerados como espacios
en blanco por otros languajes no son considerados como espacios en blanco por
awk.
El propósito de los campos es facilitar al usuario
la referencia a las partes constituyentes de un registro (tratar las subpartes
de un registro). No tienes que usarlos puedes operar con el registro completo
si es lo que deseas pero los campos son los que hacen a los programas awk más sencillos tan potentes.
Para referirse a un campo en un programa awk, usas un signo de dólar $, seguido por el número de campo que desees.
Por lo tanto, $1 se refiere al primer campo, $2 se refiere al segundo, y así
sucesivamente. Por ejemplo, supón que lo siguiente es una línea del fichero
de entrada:
This seems like a pretty nice example.
Aquí el primer campo, o $1, es This;
el segundo campo, o $2, es seems; y así sucesivamente. Advierta que el último
campo, $7, es example.. Ya que no hay espacios en blanco entre la e y el
punto final de la frase ., el punto se considera como parte del campo séptimo.
No importa cuantos campos existan, el último campo
de un registro puede ser representado por $NF. Por lo que, en el ejemplo anterior, $NF sería lo mismo que $7, o lo que es lo mismo example..
Si intentas referirte a un campo más allá del último, tal como $8 cuando el
registro tiene solo 7 campos, obtienes la cadena vacía.
NF, sin el dólar delante, es una variable implícita cuyo
valor es el número de campos en el registro actual. $0, lo cual parece un intento de acceder al campo cero,
es un caso especial: representa el registro de entrada completo. Esto es lo
que usarías cuando no estuvieses interesado en campos. Aquí están algunos ejemplos
más:
awk '$1 ~ /foo/ { print $0 }' ListaBBS
Este ejemplo imprime cada registro del fichero ListaBBS
cuyo primer campo contiene la cadena foo. El operador ~ se le llama operador
de encaje, búsqueda o matching (Ver la sección Expresiones de Comparación);
chequea si una cadena (aquí, el campo $1) encaja con una expresión regular dada.
En contraste, el siguiente ejemplo:
awk '/foo/ { print $1, $NF }' ListaBBS
busca foo en el registro completo e imprime el primer y el último campo de cada registro de entrada que contenga el patrón foo.
El número de un campo no necesita ser una constante.
Cualquier expresión del lenguaje awk puede ser usado después de un $ para referirse a
un campo. El valor de la expresión especifica el número de campo. Si el valor
es una cadena, en lugar de un número, dicha cadena se convierte a número. Considere
este ejemplo:
awk '{ print $NR }'
Recuerde que NR es el número de registros leídos hasta el momento: 1
para el primer registro, 2 para el segundo, etc. Así que este ejemplo imprimiría
el primer campo del primer registro, el segundo campo del segundo registro,
y así sucesivamente. Para el registro veinte, se imprimiría el campo número
20; es probable que el registro tenga menos de 20 campos, así que imprimiría
una línea en blanco.
Aquí tienes otro ejemplo de la utilización de una expresión como
número de campo:
awk '{ print $(2*2) }' ListaBBS
El lenguaje awk debe evaluar la expresión (2*2) y usar su valor como el número del campo
a imprimir. El signo * representa multiplicación, así que la expresión 2*2
toma el valor 4. Los paréntesis son usados para que la multiplicación se realice
antes que la operación $; son necesarios donde quiera que haya un operación
binario en la expresión número de campo. Este ejemplo, entonces, imprime las
horas de operación (el cuarto campo) para cada línea del fichero ListaBBS.
Si el número de campo toma el valor de 0, obtienes
el registro entero. Por lo que, $(2-2) tiene el mismo valor que $0. Números
de campo negativos no son permitidos.
El número de campos en el registro actual se almacena
en la variable implícita NF (Ver la sección 12. Variables
Implícitas (Built-in).
La expresión $NF no es una característica especial: es la consecuencia
directa de evaluar NF y usar su valor como número de campo.
Puedes cambiar los contenidos de un campo dentro de
un programa awk; estos cambios que awk percibe como el registro de entrada actual (La entrada real es intocable:
awk nunca modifica
el fichero de entrada). Mire este ejemplo:
awk '{ $3 = $2 - 10; print $2, $3 }' inventarioenviado
El signo - representa la substracción, de modo que
este programa reasigna el campo tres, $3, y le da el valor del campo 2 menos
el campo décimo, $2 - $10. (Ver la sección Operadores Aritméticos).
El campo dos, y el nuevo valor del campo tres son impresos.
Para poder realizar esta operación, el texto del campo
dos debe ser susceptible a ser convertido a número, la cadena de caracteres
debe ser convertida a número para que se puede realizar la operación aritmética
sobre dicho campo. El número resultante de la sustracción se convierte de nuevo
a cadena de caracteres cuando se convierte en el campo tercero. Ver la sección
Conversiones de Cadenas y Números.
Cuando cambias el valor de un campo (como es percibido
por awk), el texto del registro de entrada es recalculado para contener el nuevo
campo en la posición en la que estaba el antiguo. Por lo tanto, $0 cambia para
reflejar el campo alterado. Por lo que,
awk '{ $2 = $2 - 10; print $0 }' inventarioenviado
imprime una copia del fichero de entrada, restándole 10 unidades a cada uno de los valores que presenta el campo 2 para todas las líneas.
También puedes asignar contenidos a campos que están
fuera del rango. Por ejemplo:
awk '{ $6 = ($5 + $4 + $3 + $2) ; print $6 }' inventarioenviado
Acabamos de crear el campo $6, cuyo valor es la suma de los campos
$2, $3, $4, y $5. El signo + representa la suma. Para el fichero inventarioenviado,
$6 representa el número total de objetos embarcados para un mes en particular.
La creación de un nuevo campo cambia la copia interna
del registro de entrada actual que tiene awk
el valor de $0. Por lo que, si realiza un print $0 después de añadir un
campo, el registro impreso incluye el nuevo campo, con el número de separadores
de campo apropiado entre el nuevo campo y los campos existentes previamente.
Esta recomputación afecta y se ve afectada por varias
características todavía no discutidas, en particular, el separador de campos
de salida, OFS, que se usa para separar los campos (Ver la sección
Separadores
de la Salida), y NF (el número de campos; Ver la sección Examinando campos).
Por ejemplo, el valor de NF se fija al número del campo
mayor que hayas creado.
Anotar, sin embargo, que referenciar a un campo
fuera de rango no cambia ni el valor de $0 ni el de NF. El referenciar
a un campo fuera de rango produce simplemente una cadena nula. Por ejemplo:
if ($(NF+1) != "")
print "no puede ocurrir"
else
print "todo es normal"
imprimiría `todo es normal', ya que NF+1 está fuera de rango ciertamente (Ver la sección La Sentencia if, para más información sobre las sentencias de awk if-else).
El modo en el que awk
divide los registros de entrada en campos es controlada por el separador
de campo, el cual es un carácter simple o una expresión regular. Awk recorre el registro de entrada en búsqueda de
coincidencias del separador de campos; los campos son el texto que se encuentra
entre dichos separadores de campos encontrados. Por ejemplo, si el separador
de campos es oo, entonces la siguiente línea:
moo goo gai pan
será particionada en tres campos: `m', ` g' y ` gai pan'.
El separador de campos está representado por la variable implícita
FS. ¡Que tomen nota los programadores de la Shell! Awk
no usa el nombre IFS el cual es usado por la shell. Puedes cambiar el valor
de FS en el programa awk con el operador asignación, = (Ver la sección
Expresiones de Asignación).
A menudo el momento adecuado para hacer esto es el principio de la ejecución,
antes de que se procese ninguna entrada, de forma que el primer registro se
lea con el separador adecuado. Para hacer esto, use el patrón especial BEGIN (Ver la sección Los Patrones Especiales BEGIN y END).
Por ejemplo, aquí hemos fijado el valor de la variable FS a la cadena ,:
awk 'BEGIN { FS = "," } ; { print $2 }'
Dada la siguiente línea,
John Q. Smith, 29 Oak St., Walamazoo, MI 42139
Este programa awk extrae la cadena `29 Oak St.'.
Algunas veces tus datos de entrada contendrán caracteres
separadores que no separen los campos de la forma que tu pensabas que debieran
estar separados. Por ejemplo, los nombres de personas en el ejemplo que hemos
estado usando podría tener un título o sufijo acoplado, tal como `John Q. Smith,
LXIX'. Para la entrada que contuviese dicho nombre:
John Q. Smith, LXIX, 29 Oak St., Walamazoo, MI 42139
El programa de ejemplo anterior extraería `LXIX', en lugar de
`29 Oak St.'. Si estabas esperando que el programa escribiese la dirección,
serías sorprendido. Así que elige la disposición de tus datos y separadores
de campos cuidadosamente para prevenir tales problemas.
Como ya sabes, por defecto, los campos son separados
por secuencias de espacios en blanco (espacios y tabuladores), no por espacios
simples: dos espacios en una fila no delimitan un campo vacío. El valor por
defecto del separador de campos es una cadena que contiene un único espacio.
Si este valor fuese interpretado de la forma usual, cada carácter espacio separaría
campos, de forma que dos espacios en una fila crearían un campos vacío entre
ellos. La razón por lo que esto no ocurre es porque un espacio simple como valor
de FS es un caso especial: se toma para especificar la manera por defecto de
deliminar campos.
Si FS es cualquier otro carácter simple, tal y como
,, cada ocurrencia de dicho carácter separa dos campos. Dos ocurrencias consecutivas
delimitan un campo vacío. Si el carácter ocurre al comienzo o al final de la
línea, eso también delimita un campo vacío. El carácter espacio es el único
carácter que no sigue estas reglas.
Más generalmente, el valor de FS podría ser una cadena
que contuviese una expresión regular. Entonces cada coincidencia en el registro
de la expresión regular separa campos. Por ejemplo, la asignación:
FS = ", \t"
hace que cada área de una línea de entrada que consista en una coma seguida de un espacio y un tabulador sea un separador de campo (\t representa el tabulador).
Para un ejemplo menos trivial de una expresión regular,
supón que deseas que los espacios simples separen los campos de la misma forma
que lo harían unas comas si fuesen usadas. Le podrías asignar a FS
el valor
[ ]. Esta expresión regular concuerda con un único espacio
y nada más.
El valor de FS puede ser fijado en la línea de comando.
Use el argumento -F para hacerlo. Por ejemplo:
awk -F, 'program' input-files
fija FS para que sea el carácter ,. Dese cuenta de que el argumento aparece en mayúsculas -F. Esto contrasta con -f, el cual especifica un fichero que contiene un programa awk. La distinción entre mayúsculas y minúsculas es significativa en las opciones de comando: las opciones -F y -f no tienen nada que ver la una con la otra. Puedes usar ambas opciones al mismo tiempo para fijar el argumento FS y para decirle a awk que el programa se encuentra en un determinado fichero.
Un caso especial, en modo compatibilidad (Ver la sección
14. Invocación de awk),
si el argumento a -F es t, entonces el FS es fijado al carácter tabulador.
(Esto es porque si tú tecleas -F\t, sin las comillas, en el shell, el carácter
\ es eliminado, de forma que awk supone que tú realmente quieres que tus campos estén separados por tabuladores,
y no por ts. Use FS=T en la línea de comando si deseas realmente que tus
campos aparezcan separados por ts.)
Por ejemplo, utilicemos un fichero de programa awk llamado baud.awk que contiene el patrón /300/, y la acción print $1. Aquí se presenta
el programa:
/300/ { print $1 }
Fijemos también el valor de FS al carácter -, y
ejecute el programa sobre el fichero ListaBBS El siguiente comando imprime
una lista de los nombres del bulletin boards que operan a 300 baudios y los
tres primeros dígitos de sus números de teléfono:
awk -F- -f baud.awk ListaBBS
Produce la siguiente salida:
aardvark 555
alpo
barfly 555
bites 555
camelot 555
core 555
fooey 555
foot 555
macfoo 555
sdace 555
sabafoo 555
Dese cuenta de la segunda línea de la salida. Si chequeas el
fichero original, verás que la segunda línea presenta lo siguiente:
alpo-net 555-3412 2400/1200/300 A
El guíon - como parte del nombre del sistema fue utilizado
como separador de campo, en lugar del guión que aparecía en el número de teléfono
que era lo que se pretendía. Esto te demuestra porqué tienes que ser cuidadoso
a la hora de elegir tus separadores de campo y registro.
El siguiente programa busca en el fichero de sistema password,
e imprime las entrada de aquellos usuarios que no tiene password:
awk -F: '$2 == ""' /etc/passwd
Aquí usamos la opción -F de la línea
de comando para fijar el separador de campo. Advierta que los campos en /etc/passwd
están separados por dos puntos. El segundo campo representa una password de
usuario encriptada, pero si el campo está vacío, dicho usuario no tiene password.
En algunas bases de datos, una sola línea no puede
guardar convenientemente la información de un registro. En tales casos, puedes
usar registros de líneas múltiples.
El primer paso para hacer esto es elegir el formato
de tus datos: cuando los registros no vienen definidos como líneas simples,
¿cómo quieres definirlos? ¿qué debería separar los registros?
Una técnica es usar un carácter inusual o cadena para
separar los registros. Por ejemplo, podrías usar el carácter formfeed (escrito
\f en awk, como en C) para separarlos, haciendo que cada registro fuese una página
del fichero. Para hacer esto, simplemente fija la variable RS a \f (una cadena
que contenga el carácter formfeed) Cualquier otro carácter podría ser usado
igualmente, siempre y cuando dicho carácter nunca forme parte de los datos posibles
de un registro.
Otra técnica es tener registros separados por líneas
en blanco. Como dispensación especial, una cadena nula como valor de RS indica
que los registros estarán separados por una o más líneas en blanco. Si le das
a la variable RS el valor cadena nula, un registro siempre acaba en la primera
línea en blanco que encuentra. Y el siguiente registro no comienza hasta que
no se encuentra la siguiente línea que no sea una línea en blanco no importa
cuantas líneas en blanco aparezcan en una fila, son consideradas como un único
separador de registro.
El segundo paso es separar los campos del registro.
Una forma para hacer esto es poner cada campo en una línea por separado: para
hacer esto, fija la variable FS a la cadena \n. (Esta expresión regular simple
concuerda con un simple carácter newline).
Otra idea es dividir cada línea en campos de la forma
normal. Esto ocurre por defecto como resultado de una característica especial:
cuando RS se fija a la cadena nula, el carácter newline siempre actúa
como un separador de campo. Esto es una adición a cuales quiera separaciones
de campos resultantes de FS.
Hasta ahora hemos estado obteniendo nuestros ficheros
de entrada desde el stream de entrada principal de awk
o la entrada estándar (normalmente tu terminal) o los ficheros especificados
en la línea de comandos. El Lenguaje awk
tiene un comando implícito especial llamado getline que puede ser usado para
leer la entrada bajo tu control explícito.
Este comando es bastante complejo y no debería ser
usado por principiantes. Se explica aquí porque este es el capítulo de la entrada.
Los ejemplos que siguen a la explicación del comando getline incluyen material
que no ha sido explicado todavía. Por lo tanto, vuelve a estudiar el comando
getline después de haber visto el manual completo y que tengas un buen conocimiento
de cómo funciona awk.
El comando getline devuelve un 1 si encuentra un registro,
y 0 si se encuentra el final del fichero. Si se produce algún error al obtener
un registro, debido por ejemplo a que dicho fichero no pueda ser abierto, entonces
getline devolverá un 1.
En los siguientes ejemplos, comando representa
una cadena que representa un comando del shell.
Getline
El comando getline puede ser usado sin argumentos
para leer la entrada del fichero de entrada actual. Todo lo que hace en este
caso es leer el siguiente registro de entrada y dividirlo en campos. Esto es
útil cuando has acabado de procesar el registro actual y no vas a realizar ninguna
alteración del mismo y quieres procesar justo en ese momento el siguiente registro.
Aquí tienes un ejemplo:
awk '{
if (t = index($0, "/*")) {
if(t > 1)
tmp = substr($0, 1, t - 1)
else
tmp = ""
u = index(substr($0, t + 2), "*/")
while (! u) {
getline
t = -1
u = index($0, "*/")
}
if(u <= length($0) - 2)
$0 = tmp substr($0, t + u + 3)
else
$0 = tmp
}
print $0
}'
Este programa awk
borra todos los comentarios, `/* ... */', de la entrda. Sustituyendo el comando
print $0 con otras sentencias, podrías realizar un procesamiento más complejo
sobre la entrada comentada, tal y como buscar si casa con una expresión regular.
Esta forma del comando getline fija el valor de NF
(el número de campos; Ver la sección Examinando campos),
NR (el número de registros leídos hasta ahora, Ver la sección Cómo se particiona la Entrada
en Registros), FNR (el número de registros
leídos del fichero de entrada actual), y el valor de $0.
Nota: el nuevo valor de $0 se usa
en el chequeo de los patrones de las reglas subsiguientes. El valor original
de $0 que disparó la regla que ejecutó getline se pierde. Por contraste, la
sentencia next lee un nuevo registro pero inmediatamente comienza a procesarlo
normalmente, comenzando con la primera regla del programa. Ver la sección La Sentencia next.
Getline variable
Esta forma de getline lee un registro en la variable
variable. Esto es útil cuando quieres que tu programa lea el siguiente
registro del fichero de entrada actual, pero no quieres someter el registro
que leas al procesamiento de la entrada normal.
Por ejemplo, supón que la siguiente línea es un comentario,
o una cadena especial, y quieres leerla, pero quieres realizar lo que sea que
no dispare ninguna regla. Esta versión de getline te permite leer esa línea
y almacenarla en una variable de forma que el bucle principal de leer una línea
y chequearla contra todas las reglas nunca llega a conocer dicha línea.
El siguiente ejemplo alterna (swaps) cada dos líneas
de entrada. Por ejemplo, dado:
wan
tew
free
phore
produce la siguiente salida:
tew
wan
phore
free
Aquí tienes el programa:
awk '{
if ((getline tmp) > 0) {
print tmp
print $0
} else
print $0
}'
La función getline usada de esta forma fija solamente
las variables NR y FNR ( y por supuesto, variable). El registro no es
dividido en campos, de forma que los valores de los campos (incluyendo $0)
y el valor de la variable NF no cambia.
getline < fichero
Esta forma de la función getline toma su entrada desde
el fichero fichero. Aquí fichero es una expresión que se trata
como una cadena que contiene el nombre del fichero. A la expresión <fichero
se le llama redirección ya que direcciona la entrada para que venga desde un
lugar diferente.
Esta forma es útil si quieres leer la entrada de un
fichero en particular, en lugar de la stream de entrada principal. Por ejemplo,
el siguiente programa lee su registro de entrada del fichero foo.input cuando
encuentra un primer campo con un valor igual a 10 en el fichero de entrada actual.
awk '{
if ($1 == 10) {
getline < "foo.input"
} else
}'
Debido a que el stream de entrada principal
no se usa, los valores de NR y FNR no se cambian. Pero el registro leído es
partido en campos como si fuera un registro normal, por lo que los valores de
$0 y otros campos son cambiados. Lo mismo le ocurre al valor de NF. Esto hace
que el registro leído no sea chequeado contra todos los patrones del programa
awk,
del mismo modo que ocurriría si el registro hubiese sido leído normalmente por
el bucle principal de proceso de awk.
Sin embargo el nuevo registro es chequeado contra las reglas restantes, del
mismo modo que ocurría cuando se usaba getline sin la redirección.
getline variable < fichero
Esta forma de la función getline toma su entrada del
fichero fichero y la pone en la variable variable. Como anteriormente,
fichero es una expresión cuyo valor es una cadena, la cual especifica
el fichero del que se va a leer.
En esta versión de getline, ninguna de las variable
implícitas cambia su valor, y el registro no es dividido en campos. La única
variable que cambia es variable. Por ejemplo, el siguiente programa copia
todos los ficheros de entrada a la salida, excepto los registros que dicen `@include
nombre_fichero'. Tales registros son reemplazados por el contenido del
fichero nombre_fichero.
awk '{
if (NF == 2 && $1 == "@include") {
while ((getline line < $2) > 0)
print line
close($2)
} else
}'
Advierta aquí como el nombre del fichero de entrada
extra no se construye en el programa; es cogido de los datos, del segundo campo
de las líneas @include.
La función close se llama para asegurarse que si aparecen
dos líneas @include idénticas, el fichero especificado entero se incluye dos
veces. Ver la sección Cerrado de Ficheros de Entrada
y Pipes.
Una deficiencia de este programa es que no procesa
las sentencias @include anidadas del mismo modo que un preprocesador de macros
haría.
comando ¦ getline
Puedes hacer un pipe de la salida a un comando a getline.
Un pipe es simplemente una forma de enlazar la salida de un programa con la
entrada de otro. En este caso, la cadena comando es ejecutada como un
comando de la shell y su salida es pipeada dentro de awk para que sea usado como entrada. Esta forma de getline lee un registro
del pipe.
Por ejemplo, el siguiente programa copia la entrada
a la salida, excepto las líneas que comienzan con @execute, las cuales son
reemplazadas por la salida producida por la ejecución del resto de la línea
como un comando de shell:
awk '{
if ($1 == "@execute") {
tmp = substr($0, 10)
while ((tmp ¦ getline) > 0)
close(tmp)
} else
}'
La función close se usa para asegurarse de que si
aparecen dos líneas @execute idénticas, el comando se ejecute de nuevo para
cada línea. Ver la sección Cerrado de Ficheros de Entrada
y Pipes.
Dada la siguiente entrada:
foo
bar
baz
@execute who
bletch
el programa podría producir:
foo
bar
baz
hack ttyv0 Jul 13 14:22
hack ttyp0 Jul 13 14:23 (gnu:0)
hack ttyp1 Jul 13 14:23 (gnu:0)
hack ttyp2 Jul 13 14:23 (gnu:0)
hack ttyp3 Jul 13 14:23 (gnu:0)
bletch
Dese cuenta de que este programa ejecutó el comando
who e imprimió el resultado.
Esta variación de getline divide el registro en campos,
fija el valor de NF y recalcula el valor de $0. Los valores de NR y FNR no son cambiados.
comando ¦ getline variable
La salida del comando comando se envía a través
de un pipe a getline y a la variable variable. Por ejemplo, el siguiente
programa lee la hora y día actual a la variable tiempo_actual, usando la utilidad
llamada date, y después la imprime.
awk 'BEGIN {
"date" ¦ getline tiempo_actual
close("date")
print "Report printed on " tiempo_actual
}'
En esta versión de getline, ninguna
de las variable implícitas es cambiada, y el registro no se divide en campos.
Si se usa el mismo nombre de fichero o el mismo comando shell
se usa con getline más de una vez durante la ejecución de un programa awk,
el fichero es abierto (o el comando es ejecutado) sólo la primera vez. En ese
momento, el primer registro de la entrada es leído de ese fichero o comando.
La próxima vez que se use ese mismo nombre de fichero o comando con getline,
otro registro se leerá de él, y así sucesivamente.
Esto implica que si quieres comenzar la lectura del mismo fichero
desde el principio, o si quieres volver a ejecutar un comando (en lugar de leer
más salida del comando), debes realizar unos pasos especiales. Lo que puedes
usar es la función close, tal y como sigue:
close(fichero)
o
close(comando)
El argumento fichero o comando puede
ser cualquier expresión. Su valor debe ser exactamente el mismo que la cadena
que fue usada para abrir el fichero o comenzar el comando por ejemplo, si
abres un pipe con esto:
"sort -r names" ¦ getline foo
entonces debes cerrar el pipe de esta forma:
close("sort -r names")
Una vez que se ejecuta esta llamada
a la función, el siguiente getline de ese fichero o comando reabrirá el fichero
o reejecutará el comando.
Manual |