Eu tenho o seguinte fluxo tcpdump:
Current:
07:36:03.848461 IP 172.17.3.41.33101 > 172.17.3.43.17408: UDP, length 44
07:36:03.848463 IP 172.17.3.42.33101 > 172.17.3.43.17409: UDP, length 44
07:36:03.848467 IP SYSTEM-A.33101 > 172.17.3.43.17418: UDP, length 45
07:36:03.848467 IP SYSTEM-B.33101 > 172.17.3.43.17419: UDP, length 45
Os números de porta estão em decimal. Como posso canalizá-lo para sed ou awk para modificar o fluxo para que seja o mesmo fluxo com os números de porta alterados para hexadecimal:
Expected:
07:36:03.848461 IP 172.17.3.41.814d > 172.17.3.43.4400: UDP, length 44
07:36:03.848463 IP 172.17.3.42.814d > 172.17.3.43.4401: UDP, length 44
07:36:03.848467 IP SYSTEM-A.814d > 172.17.3.43.440a: UDP, length 45
07:36:03.848467 IP SYSTEM-B.814d > 172.17.3.43.440b: UDP, length 45
Se eu tiver o número da porta, uso isso para convertê-lo em hexadecimal:
echo 33101 | sed -e 's/.*://' | xargs printf "%x\n"
814d
Eu tenho tentado resolver isso, mas sem sorte. Como posso substituir os números de porta após a última ocorrência de '.'
na terceira e quinta coluna do fluxo e, em seguida, alterá-lo para hexadecimal em tempo real?
Com
perl
:Que procura palavras que consistem em um espaço em branco (
\s
) seguido por uma sequência de um ou mais (+
) não-espaço em branco (\S
), um ponto e uma sequência de um ou mais dígitos (\d+
) e substitui a parte final (cujo início é marcado com\K
) com o mesmo ($&
) formatado em hex
adecimal (g
lobalmente, sendo a substituiçãoe
avaliada como código perl).Com qualquer awk em qualquer shell em cada caixa UNIX:
Com GNU awk para o 3º argumento para combinar():
Se os números dos campos forem constantes - como nos campos 3 e 5 da sua pergunta - tente
Por exemplo, dois pontos à direita no campo 5:
Primeiro deve-se perguntar se isso é sensato, tendo
172.17.3.43.440a
onde os primeiros 4 campos separados por período são decimais e o quinto é hexadecimal parece estranho. No entanto, vamos supor que o OP tenha boas razões.O OP nos deu alguns dados de exemplo e a saída desejada, isso é muito útil.
O OP nos mostra o
echo 33101 | sed -e 's/.*://' | xargs printf "%x\n"
que nos dá algumas dicas sobre seus processos de pensamento. Isso me diz que eles estão no caminho errado. Eles querem quebrar a linha de alguma forma (usandoawk
oused
com base nas tags), usarprintf
para convertê-la em hexadecimal e depois remontar a linha. Repita para cada linha. Embora obviamente isso possa funcionar, é muito lento. Os processos Unix e Linux são baratos, mas não gratuitos. Essa abordagem usará muitos processos por linha, e pode-se esperar que uma saída de fluxo tcpdump tenha muitas centenas de linhas. É desejável fazer a alteração usando apenas alguns processos por arquivo para que isso tenha velocidade razoável, se possível.Então vamos para a escolha da ferramenta. As tags sugerem
sed
eawk
. eu rejeitariased
. Éturing complete
(assumindo uma quantidade infinita de memória) e, portanto, pode fazer qualquer coisa que possa ser feita em qualquer outra linguagem, mas isso não significa dizer que será fácil ou legível. Se eu estivesse fazendo isso, provavelmente usariaperl
oupython
, masawk
é perfeitamente razoável, então vamos usar isso.awk
programas percorrem as linhas sozinhos, então este é um bom começo. O OP fala sobre othird column
, mas olhando para a saída desejada, eles também querem o quinto. Eles não querem os milissegundos na primeira coluna convertidos em hexadecimal, embora isso também seja um númeroafter last occurrence of '.'
. Portanto, há uma escolha a ser feita, fazemos um loop sobre cada uma das colunas (chamadas "campos" em awk) após a primeira ou apenas fazemos a terceira e a quinta? Qualquer um funcionaria. Vamos pegar o caso geral e fazer todas as colunas. Isso nos dáAgora precisamos ver se o campo corresponde a um
.
seguido de um número e depois um opcional:
(assim convertemos o 5º campo nos dados originais). Isso pode ser feito com uma expressão regular, uma das ideias poderosas que o Unix popularizou.Então agora para fazer a conversão. Use
match
para quebrar o padrão e sprintf para colocá-lo de volta, para obter o programa finalObrigado a todos por suas respostas! Todos funcionam! No entanto, gostaria de postar minha solução aqui também. Agora eu sei que pedi especificamente
sed
eawk
por isso, mas minha entrada é umtcpdump
fluxo e eu queria modificar os números de porta para hexadecimal. Então eu passei pelo código-fonte e alterei as seguintes linhas:(void)snprintf(buf, sizeof(buf), "%u", i);
para
(void)snprintf(buf, sizeof(buf), "%u", i);
para
Compilou o binário e agora o tcpdump imprime as portas em hexadecimal.