texto reemplazar practicos examples ejemplos comando linux awk

linux - reemplazar - sed ''s///g''



¿Los patrones awk pueden coincidir con múltiples líneas? (5)

Tengo algunos archivos de registro complejos que necesito para escribir algunas herramientas para procesarlos. He estado jugando con awk, pero no estoy seguro de que awk sea la herramienta adecuada para esto.

Mis archivos de registro son copias impresas de las decodificaciones del protocolo OSPF que contienen un registro de texto de los distintos paquetes de protocolo y sus contenidos con sus diversos campos de protocolo identificados con sus valores. Quiero procesar estos archivos e imprimir solo ciertas líneas del registro que pertenecen a pkts específicos. Cada registro de pkt puede consistir en un número variable de líneas para la entrada de ese pkt.

Parece que awk puede procesar una sola línea que coincide con un patrón. Puedo ubicar el paquete deseado pero luego debo hacer coincidir los patrones en las líneas que siguen para determinar si es un paquete que deseo imprimir.

Otra forma de ver esto es que me gustaría aislar varias líneas en el archivo de registro e imprimir aquellas líneas que son los detalles de un pkt particular basado en coincidencias de patrones en varias líneas.

Dado que awk parece estar basado en líneas, no estoy seguro de si esa sería la mejor herramienta para usar.

Si awk puede hacer esto, ¿cómo se hace? Si no, ¿alguna sugerencia sobre qué herramienta usar para esto?


Awk es realmente basado en el registro. Por defecto, piensa en una línea como un registro, pero puede modificarla con la variable RS (separador de registros).

Una forma de abordar esto sería hacer una primera pasada utilizando sed (también podría hacerlo con awk, si lo prefiere), para separar los registros con un carácter diferente, como un feed de formularios. Luego, puede escribir su script awk donde tratará el grupo de líneas como un solo registro.

Por ejemplo, si esta es su información:

animal 0 name: joe type: dog animal 1 name: bill type: cat animal 2 name: ed type: cat

Para separar los registros con feeds de formularios:

$ cat data | sed $''s|^/(animal.*/)|/f//1|''

Ahora tomaremos eso y lo pasaremos por awk. Aquí hay un ejemplo de impresión condicional de un registro:

$ cat data | sed $''s|^/(animal.*/)|/f//1|'' | awk '' BEGIN { RS="/f" } /type: cat/ { print }''

salidas:

animal 1 name: bill type: cat animal 2 name: ed type: cat

Edición: como beneficio adicional, aquí está cómo hacerlo con awk-ward ruby ​​(-014 significa usar form-feed (código octal 014) como separador de registros):

$ cat data | sed $''s|^/(animal.*/)|/f//1|'' | ruby -014 -ne ''print if /type: cat/''


Awk puede detectar fácilmente combinaciones de patrones de varias líneas, pero necesita crear lo que se denomina una máquina de estados en su código para reconocer la secuencia.

Considere esta entrada:

how second half #1 now first half second half #2 brown second half #3 cow

Como has visto, es fácil reconocer un solo patrón. Ahora, podemos escribir un programa awk que reconozca la segunda mitad solo cuando está precedido directamente por una primera mitad . (Con una máquina de estados más sofisticada podría detectar una secuencia arbitraria de patrones).

/second half/ { if(lastLine == "first half") { print } } { lastLine = $0 }

Si ejecuta esto verá:

second half #2

Ahora, este ejemplo es absurdamente simple y apenas una máquina de estados. El estado interesante solo dura la duración de la instrucción if y el estado anterior es implícito, dependiendo del valor de lastLine. En una máquina de estado más canónica, mantendría una variable de estado explícita y la transición de estado a estado, dependiendo del estado existente y la entrada actual. Pero es posible que no necesite mucho mecanismo de control.


Hago este tipo de cosas con los registros de sendmail, de vez en cuando.

Dado:

Jan 15 22:34:39 mail sm-mta[36383]: r0B8xkuT048547: to=<www@web3>, delay=4+18:34:53, xdelay=00:00:00, mailer=esmtp, pri=21092363, relay=web3., dsn=4.0.0, stat=Deferred: Operation timed out with web3. Jan 15 22:34:39 mail sm-mta[36383]: r0B8hpoV047895: to=<www@web3>, delay=4+18:49:22, xdelay=00:00:00, mailer=esmtp, pri=21092556, relay=web3., dsn=4.0.0, stat=Deferred: Operation timed out with web3. Jan 15 22:34:51 mail sm-mta[36719]: r0G3Youh036719: from=<[email protected]>, size=0, class=0, nrcpts=0, proto=ESMTP, daemon=IPv4, relay=[50.71.152.178] Jan 15 22:35:04 mail sm-mta[36722]: r0G3Z2SF036722: lost input channel from [190.107.98.82] to IPv4 after rcpt Jan 15 22:35:04 mail sm-mta[36722]: r0G3Z2SF036722: from=<[email protected]>, size=0, class=0, nrcpts=0, proto=SMTP, daemon=IPv4, relay=[190.107.98.82] Jan 15 22:35:36 mail sm-mta[36728]: r0G3ZXiX036728: lost input channel from ABTS-TN-dynamic-237.104.174.122.airtelbroadband.in [122.174.104.237] (may be forged) to IPv4 after rcpt Jan 15 22:35:36 mail sm-mta[36728]: r0G3ZXiX036728: from=<[email protected]>, size=0, class=0, nrcpts=0, proto=SMTP, daemon=IPv4, relay=ABTS-TN-dynamic-237.104.174.122.airtelbroadband.in [122.174.104.237] (may be forged)

Yo uso un script como este:

#!/usr/bin/awk -f BEGIN { search=ARGV[1]; # Grab the first command line option delete ARGV[1]; # Delete it so it won''t be considered a file } # First, store every line in an array keyed on the Queue ID. # Obviously, this only works for smallish log segments, as it uses up memory. { line[$6]=sprintf("%s/n%s", line[$6], $0); } # Next, keep a record of Queue IDs with substrings that match our search string. index($0, search) { show[$6]; } # Finally, once we''ve processed all input data, walk through our array of "found" # Queue IDs, and print the corresponding records from the storage array. END { for(qid in show) { print line[qid]; } }

para obtener el siguiente resultado:

$ mqsearch airtel /var/log/maillog Jan 15 22:35:36 mail sm-mta[36728]: r0G3ZXiX036728: lost input channel from ABTS-TN-dynamic-237.104.174.122.airtelbroadband.in [122.174.104.237] (may be forged) to IPv4 after rcpt Jan 15 22:35:36 mail sm-mta[36728]: r0G3ZXiX036728: from=<[email protected]>, size=0, class=0, nrcpts=0, proto=SMTP, daemon=IPv4, relay=ABTS-TN-dynamic-237.104.174.122.airtelbroadband.in [122.174.104.237] (may be forged)

La idea aquí es que estoy imprimiendo todas las líneas que coincidan con el ID de la cola de Sendmail de la cadena que quiero buscar. La estructura del código es, por supuesto, un producto de la estructura del archivo de registro, por lo que deberá personalizar su solución para los datos que está tratando de analizar y extraer.


awk puede procesar desde el patrón de inicio hasta el patrón final

/start-pattern/,/end-pattern/ { print }

Estaba buscando como emparejar

* Implements hook_entity_info_alter(). */ function file_test_entity_type_alter(&$entity_types) {

tan creado

//* Implements hook_/,/function / { print }

Que el contenido que necesitaba. Un ejemplo más complejo es omitir líneas y eliminar elementos no espaciales. Note awk es una herramienta de registro (línea) y palabra (división por espacio).

# start,end pattern match using comma / /* Implements hook_(.*?)/./,/function (./S*?)/ { # skip PHP multi line comment end $0 ~ / /*/// skip # Only print 3rd word if ($0 ~ /Implements/) { hook=$3 # scrub of opening parenthesis and following. sub(//(.*$/, "", hook) print hook } # Only print function name without parenthesis if ($0 ~ /function/) { name=$2 # scrub of opening parenthesis and following. sub(//(.*$/, "", name) print name print "" } }

Espero que esto ayude también.

Ver también ftp://ftp.gnu.org/old-gnu/Manuals/gawk-3.0.3/html_chapter/gawk_toc.html


`pcregrep -M` works pretty well for this.

Desde pcregrep (1):

-M, --multiline

Permitir que los patrones coincidan con más de una línea. Cuando se da esta opción, los patrones pueden contener de manera útil caracteres de nueva línea literales y apariciones internas de caracteres ^ y $. La salida para una coincidencia exitosa puede consistir en más de una línea, la última de las cuales es aquella en la que terminó la coincidencia. Si la cadena coincidente termina con una secuencia de nueva línea, la salida finaliza al final de esa línea.

Cuando se establece esta opción, la biblioteca PCRE se llama en modo "multilínea". Hay un límite en el número de líneas que pueden coincidir, impuestas por la forma en que pcregrep almacena el archivo de entrada a medida que lo escanea. Sin embargo, pcregrep garantiza que al menos 8K caracteres o el resto del documento (el que sea el más corto) estén disponibles para la comparación directa, y de manera similar, los 8K caracteres anteriores (o todos los caracteres anteriores, si son menos de 8K) tienen la garantía de estar disponibles Para mirar detrás de las afirmaciones. Esta opción no funciona cuando la entrada se lee línea por línea (consulte --line-buffered).