mostrar solo partes de líneas del archivo de registro en vivo

mostrar solo partes de líneas del archivo de registro en vivo

Tenemos un archivo de registro que a menudo sigo en vivo con tail y uso grep para filtrar las líneas que me interesan. Sin embargo, las líneas contienen una gran cantidad de datos que no siempre me interesan, pero que me han resultado difíciles. analizar para que solo vea las partes de la línea que quiero. El formato de cada entrada de línea es principalmente una lista de etiquetas y los datos (a veces contienen espacios) entre comillas. Aquí hay algunos ejemplos de líneas de registro (desinfectadas):

2017:11:29-11:29:56 filter-1 httpproxy[3194]: id="0001" severity="info" sys="SecureWeb" sub="http" name="http access" action="pass" method="CONNECT" srcip="10.11.12.13" dstip="14.3.1.4" user="" group="" ad_domain="" statuscode="200" cached="0" profile="REF_HttPro1234 (Campus2)" filteraction="REF_HttStu (Allow Policy)" size="6518" request="0x915a3e00" url="https://website.net/" referer="" error="" authtime="0" dnstime="1" cattime="73" avscantime="0" fullreqtime="61576999" device="0" auth="6" ua="" exceptions="" category="9998" reputation="unverified" categoryname="Uncategorized" country="United States" application="krux" app-id="826"
2017:11:29-11:29:56 filter-1 httpproxy[3194]: id="0001" severity="info" sys="SecureWeb" sub="http" name="http access" action="pass" method="GET" srcip="10.13.14.15" dstip="154.6.75.10" user="" group="" ad_domain="" statuscode="200" cached="0" profile="REF_HttPro1235 (Campus1)" filteraction="REF_HttStu (Allow Policy)" size="3161" request="0x6b4d5610" url="http://host.com/mini_banner.png" referer="http://www.web.com/computers.htm" error="" authtime="0" dnstime="0" cattime="64" avscantime="848" fullreqtime="50046" device="0" auth="6" ua="Mozilla/5.0 (X11; CrOS x86_64 9765.85.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.123 Safari/537.36" exceptions="" category="111" reputation="trusted" categoryname="Education/Reference" sandbox="-" content-type="image/png"

Una cosa a tener en cuenta es que no todas las etiquetas están presentes en todas las líneas. Por ejemplo, la aplicación y el ID de la aplicación están presentes en la primera línea pero no en la segunda.

Usando las líneas anteriores como entrada de ejemplo, un ejemplo de lo que me gustaría tener como salida sería mostrar solo las etiquetas srcip, nombre de categoría y URL en ese orden. El resultado deseado se vería así:

10.11.12.13 Uncategorized https://website.net/
10.13.14.15 Education/Reference http://host.com/mini_banner.png

Estoy buscando una solución que sea fácilmente adaptable para poder modificar sobre la marcha qué etiquetas se muestran.

Respuesta1

Sus datos están altamente estructurados comoclave="valor", por lo que puedes escribir un pequeño script de shell usando gnu awk que toma como argumento una lista de nombres de claves y simplemente imprime esos valores. P.ej, myscript:

#!/bin/bash
awk -v lhs="$*" '
BEGIN{  FPAT = "[a-z-]*=\"[^\"]*\""
        nwant = split(lhs,want)
}
{       for(i=1;i<=NF;i++){
            start = match($i,/([a-z-]*)="([^"]*)"/,a)
            key[a[1]] = a[2]
        }
        for(i=1;i<=nwant;i++){printf "%s ",key[want[i]]; key[want[i]] = ""}
        printf "\n"
}'

al que llamas como myscript srcip categoryname url. Esto establece la variable awk lhspara los argumentos como una sola cadena, que se divide en una matriz wantal principio. Las líneas se dividen mediante awk en campos que coinciden con el patrón.clave="valor"utilizando la FPATvariable incorporada.

En cada línea, para cada campo lo dividimos match()en 2 grupos capturados, para la clave y para la parte entre comillas dobles. Estos se colocan mediante awk en una matriz ay los guardamos en una matriz asociativa keyindexada por la cadena de clave.

Luego, para cada clave deseada, imprimimos el valor y lo borramos para la siguiente línea (en caso de que esa línea no tenga esta clave). Obviamente, esto supone que todos los datos tienen la estructura requerida y necesitarán cambios para manejar (") dentro del valor o claves con caracteres no alfabéticos.


Las versiones de gnu awk (gawk) anteriores a la 4.0 no tienen la FPATfunción incorporada para dividir la línea en campos que coincidan con un patrón, por lo que debe hacerlo usted mismo:

#!/bin/bash
awk -v lhs="$*" '
BEGIN{ nwant = split(lhs,want) }
{       input = $0
        while(match(input,"[a-z-]*=\"[^\"]*\"")>0){
            field = substr(input,RSTART,RLENGTH)
            input = substr(input,RSTART+RLENGTH)
            start = match(field,/([a-z-]*)="([^"]*)"/,a)
            key[a[1]] = a[2]
        }
        for(i=1;i<=nwant;i++){printf "%s ",key[want[i]]; key[want[i]] = ""}
        printf "\n"
}'

Obviamente, puedes combinar las dos llamadas de coincidencia en una, pero esto muestra la diferencia con el original.

Respuesta2

Usando (compatible con POSIX) sed...

sed 's/.* srcip="\([^"]*\)" .* url="\([^"]*\)" .* categoryname="\([^"]*\)" .*/\1 \3 \2/' logfile

No hay nada especial aquí, simplemente busque las claves y rodee los valores con pares, \(..\)lo que permite usarlos como referencias anteriores. Luego sustituimos la cadena con solo las referencias posteriores, delimitadas por espacios, ordenadas según sus requisitos: \1 \3 \2.

Producción:

10.11.12.13 Uncategorized https://website.net/
10.13.14.15 Education/Reference http://host.com/mini_banner.png

Si los registros contienen cadenas que no tienen todas estas claves, puede usar:

sed -n 's/.* srcip="\([^"]*\)" .* url="\([^"]*\)" .* categoryname="\([^"]*\)" .*/\1 \3 \2/p' logfile

Esto sólo imprimirá líneas que coincidan con el patrón.

Y, por supuesto, si desea utilizarlos en forma de transmisión, simplemente elimine el nombre del archivo y haga[something sending logs to stdout] | sed ...

información relacionada