Procura múltiplos padrões em cada linha e imprime em um novo arquivo

0

Aqui está o arquivo de amostra. O log atual é muito maior que isso.

user@linux:~$ cat log.txt 
[24/09/2018:22:41:49 GMT] "PROXY_SERVER_BA2" c-ip=x.x.x.x cs-bytes=1198 cs-categories="Technology/Internet" cs-host=shavar.services.mozilla.com cs-ip=y.y.y.y cs-method=CONNECT cs-uri-path=/ cs-uri-port=443 cs-uri-scheme=tcp cs-User-Agent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0" cs-username=johndoe dnslookup-time=0 duration=60 rs-status=0 s-action=TCP_TUNNELED

[24/09/2018:17:45:44 GMT] "PROXY_SERVER_AA2" c-ip=x.x.x.x cs-bytes=152450 cs-categories="Business/Economy" cs-host=cvshipping.ups.com cs-ip=z.z.z.z cs-method=CONNECT cs-uri-path=/ cs-uri-port=443 cs-uri-scheme=tcp cs-User-Agent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0" cs-username=johndoe dnslookup-time=0 duration=268 rs-status=0 s-action=TCP_TUNNELED

[24/09/2018:17:44:03 GMT] "PROXY_SERVER_AA2" c-ip=x.x.x.x cs-bytes=1795 cs-categories="Software Downloads" cs-host=blocklist.addons.mozilla.org cs-ip=z.z.z.z cs-method=CONNECT cs-uri-path=/ cs-uri-port=443 cs-uri-scheme=tcp cs-User-Agent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0" cs-username=johndoe dnslookup-time=0 duration=61 rs-status=0 s-action=TCP_TUNNELED

[24/09/2018:17:41:44 GMT] "PROXY_SERVER_AA2" c-ip=x.x.x.x cs-bytes=3882 cs-categories="Web Ads/Analytics" cs-host=cebwa.d2.sc.omtrdc.net cs-ip=z.z.z.z cs-method=CONNECT cs-uri-path=/ cs-uri-port=443 cs-uri-scheme=tcp cs-User-Agent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0" cs-username=johndoe dnslookup-time=0 duration=35 rs-status=0 s-action=TCP_TUNNELED

[20/09/2018:15:48:50 GMT] "PROXY_SERVER_AA2" c-ip=a.a.a.a cs-auth-group=Domain%20Users cs-bytes=227 cs-categories="Web Ads/Analytics;Suspicious" cs-host=data35.adlooxtracking.com cs-ip=b.b.b.b cs-method=CONNECT cs-uri-path=/ cs-uri-port=443 cs-uri-scheme=tcp cs-User-Agent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0" cs-username=johndoe duration=0 rs-status=0 s-action=TCP_TUNNELED

[20/09/2018:15:48:35 GMT] "PROXY_SERVER_AA2" c-ip=a.a.a.a cs-auth-group=Domain%20Users cs-bytes=3201 cs-categories="Search Engines/Portals" cs-host=www.google.com cs-ip=b.b.b.b cs-method=CONNECT cs-uri-path=/ cs-uri-port=443 cs-uri-scheme=tcp cs-User-Agent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0" cs-username=johndoe dnslookup-time=0 duration=117 rs-status=0 s-action=TCP_TUNNELED
user@linux:~$ 

Meu objetivo é obter o registro de data e hora, a categoria e o nome do host de cada linha e redirecioná-lo para um novo arquivo.

timestamp (dentro de [ ] )

user@linux:~$ sed -n 's/^.*\[//p' log.txt | cut -d ']' -f1
24/09/2018:22:41:49 GMT
24/09/2018:17:45:44 GMT
24/09/2018:17:44:03 GMT
24/09/2018:17:41:44 GMT
20/09/2018:15:48:50 GMT
20/09/2018:15:48:35 GMT
user@linux:~$ 

hostname (após cs-host= )

user@linux:~$ sed -n 's/^.*cs-host=//p' log.txt | cut -d\  -f1
shavar.services.mozilla.com
cvshipping.ups.com
blocklist.addons.mozilla.org
cebwa.d2.sc.omtrdc.net
data35.adlooxtracking.com
www.google.com
user@linux:~$ 

category (entre cs-categories=" e " )

user@linux:~$ sed -n 's/^.*cs-categories="//p' log.txt | cut -d '"' -f1
Technology/Internet
Business/Economy
Software Downloads
Web Ads/Analytics
Web Ads/Analytics;Suspicious
Search Engines/Portals
user@linux:~$ 

Em vez de executar o comando sed um por um, é possível executar um único comando para produzir uma saída como essa?

Resultado esperado

24/09/2018:22:41:49 GMT    shavar.services.mozilla.com      Technology/Internet
24/09/2018:17:45:44 GMT    cvshipping.ups.com               Business/Economy
24/09/2018:17:44:03 GMT    blocklist.addons.mozilla.org     Software Downloads
24/09/2018:17:41:44 GMT    cebwa.d2.sc.omtrdc.net           Web Ads/Analytics
20/09/2018:15:48:50 GMT    data35.adlooxtracking.com        Web Ads/Analytics;Suspicious
20/09/2018:15:48:35 GMT    www.google.com                   Search Engines/Portals

Além disso, se você tiver uma solução melhor para isso, avise-nos.

    
por Sabrina 26.09.2018 / 16:30

3 respostas

2

Quão longe

sed -r '/^$/d; s/^[^[]*[[]([^]]*)[]].*cs-categories="([^"]*)".*cs-host=([^ ]*) .*/\t\t/' file
24/09/2018:22:41:49 GMT shavar.services.mozilla.com Technology/Internet
24/09/2018:17:45:44 GMT cvshipping.ups.com  Business/Economy
24/09/2018:17:44:03 GMT blocklist.addons.mozilla.org    Software Downloads
24/09/2018:17:41:44 GMT cebwa.d2.sc.omtrdc.net  Web Ads/Analytics
20/09/2018:15:48:50 GMT data35.adlooxtracking.com   Web Ads/Analytics;Suspicious
20/09/2018:15:48:35 GMT www.google.com  Search Engines/Portals

você?

sed -r '                        use extended regular expressions in the script
/^$/d                           delete empty lines

s/^[^[]*[[]([^]]*)[]].*         look for date time string between square brackets and prepare for 
                                the first "back reference"
cs-categories="([^"]*)".*       look for the string after cs-categories and prepare for second "b r"
cs-host=([^ ]*)                 look for the string after cs-host and prepare for third "b r"
.*/\t\t/                  create output line from back references separated by <TAB> chars.
'
    
por 26.09.2018 / 16:52
2

Usando perl com look-aheads: desta forma, não importa se o host vem antes ou depois das categorias

perl -lne '
    m(
        ^\[ (.*?) \]                   # match the timestamp
        (?=.* cs-categories= "(.+?)")  # look ahead for the category
        (?=.* cs-host= (\S+) )         # look ahead for the host
    )x
    and print join ",", $1,$2,$3
' log.txt 
    
por 26.09.2018 / 18:26
0

Que tal usar o awk:

awk '{t=""; h=""; c=""; for (i=1; i<=NF; i++) {if ($i ~ /^\[/) {t=$i} if ($i ~/^cs-host=/) {h=$i} if ($i ~ /^cs-categories=/) {c=$i}} if ((t != "") && (h != "") && (c != "")) printf("%s %s %s\n", t, h, c)}' _inputfile_

Esta é uma estimativa aproximada do que você poderia fazer. Basicamente, ele apenas percorre cada campo de espaço em branco em uma determinada linha e verifica se a linha começa com uma determinada string. Se então, coloca o valor desse campo em uma determinada variável. Depois que todos os campos tiverem sido processados, se todos os 3 campos não estiverem em branco, os campos serão impressos. Em seguida, ele passa para a próxima linha no arquivo de entrada.

Eu não fiz nada para lidar com espaço em branco na string. Você pode fazer mais verificações dentro de uma das verificações existentes para ver se a string termina com aspas duplas. Se não, anexe o próximo campo à variável.

Eu também não fiz nada com substrings para me livrar de coisas como [] e ". Eu deixo isso como um exercício para você.:)

Espero que isso ajude.

    
por 26.09.2018 / 16:50