awk filtrando captura ao vivo com arquivo como lista de padrões

awk filtrando captura ao vivo com arquivo como lista de padrões

O que estou tentando fazer é bem simples. Estou gerando saída tsharke redirecionando-a para awkwith a pipe |. Como tsharkobtém dados ao vivo, quero que awkpesquise em cada saída um padrão (alguns endereços MAC que já possuo) na primeira coluna de um arquivo ("target.txt") e, se houver uma correspondência, awkdeve gerar o primeiro e segunda coluna deste arquivo.

Exemplo de target.txt:

ab:cd:ef:gh:ij:kl,Me
12:34:56:78:90:10,You
1b:2d:3f:4h:5j:6l,someone

Para facilitar tudo, minha tsharksaída possui apenas 2 colunas, e a coluna de endereço MAC é a segunda.

1 linha de tsharksaída é como:

Jun 16, 2014 02:55:51.300286000 12:34:56:78:90:10 
           ^^^^- date and MAC are separated by tab!

Então, se tsharkfind 12:34:56:78:90:10, awka saída será

12:34:56:78:90:10 -> You

ou melhor ainda:

Jun 16, 2014 02:55:51.300286000 12:34:56:78:90:10 -> You

EDITAR #1

Bem, fiz alguns testes e descobri que tsharka saída é separada por tab\t. Não é grande coisa, mas já é uma pequena melhoria. Acontece que peguei amostras da tsharksaída e testei com a resposta do Gnoucs por meio de um echocomando antes do pipe |. Funcionou. Aí mudei o echofor tsharke tudo parou de funcionar =).

É um problema com os dados ao vivo ou algo parecido? Aqui está meu código até agora:

$ tshark -I -i wlan0 -T fields -e radiotap.dbm_antsignal -e wlan.sa | awk -F'[ ,\t]' '
     FNR == NR { a[$1] = $2 }
     ($NF in a) { print $0" -> "a[$NF] }
 ' alvos.txt -

bem, simplesmente funcionou! Provavelmente foi um erro de digitação. Obrigado por todas as respostas!

Responder1

Experimente isto:

$ awk -F'[ ,\t]' '
    FNR == NR { a[$1] = $2 }
    ($NF in a) { print $0" -> "a[$NF] }
' target.txt -

Exemplo:

$ awk -F'[ ,\t]' '
    FNR == NR { a[$1] = $2 }
    ($NF in a) { print $0" -> "a[$NF] }
' target.txt -
Jun 16, 2014 02:55:51.300286000 12:34:56:78:90:10 # Ctrl + D here
Jun 16, 2014 02:55:51.300286000 12:34:56:78:90:10 -> You

Explicação

  • -F[ ,\t]: usamos vírgula, espaço ou tabulação como separadores de campos.
  • FNR == NR { a[$1] = $2 }: FNR == NRverdadeiro apenas ao processar o primeiro arquivo. Assim, com cada linha target.txt, salvamos o segundo campo em um array associativo, sendo o primeiro campo (endereço MAC) o índice.
  • ($NF in a): Ao ler a entrada ( -após target.txtcausar awka leitura da entrada), se o último campo estiver em array associativo a, imprimimos o resultado desejado.

Responder2

Se bem entendi, qualquer um deles gerará pelo menos a saída desejada:

${TSHARK} |
sed -n "$(IFS=',
';  printf '/%s/s//& -> %s/p\n' \
        $(cat target.txt)
)"


${TSHARK} | 
sed -n "$(
   sed 's/,/|s||\& -> /
        s/.*/\\|&|p/
   ' <target.txt
)"

Eu testei isso da seguinte maneira:

printf 'ab:cd:ef:gh:ij:kl,Me
12:34:56:78:90:10,You
1b:2d:3f:4h:5j:6l,someone' >./target.txt

printf 'Jun 16, 2014 02:55:51.300286000 12:34:56:78:90:10' |
sed ...

E esta foi a minha saída:

Jun 16, 2014 02:55:51.300286000 12:34:56:78:90:10 -> You

Responder3

#!/usr/bin/env awk
# filename ~/mac-lookup.awk

function load_mac_list (filename, array) {
    while ((getline line < filename) > 0) {
        split(line, fields, ",");
        array[fields[1]] = fields[2];
    }
    close(filename)
}

BEGIN {
    load_mac_list("target.txt", mac_list);
}

($5 in mac_list) {
    print $0 " -> " mac_list[$5];
    next;
}

{
    print;   # remove this line to avoid printing unmatched lines
}

Aqui está a abordagem de força bruta. Carregue o arquivo de destino e imprima o alias do mac somente se o endereço mac estiver na lista.

Observe que, neste caso, o "target.txt" está codificado no script awk. Na resposta do Gnouc, você pode criar o script do nome do arquivo da lista de destino conforme desejado.

Uso

$ ${TSHARK} | awk -f ~/mac-lookup.awk
Jun 16, 2014 02:55:51.300286000 12:34:56:78:90:10 -> You
Jun 16, 2014 02:55:51.300286010 zy:xw:vu:ts:rq:po
Jun 16, 2014 02:55:51.300286020 ab:cd:ef:gh:ij:kl -> Me

informação relacionada