Como extrair tempo do arquivo de texto para outro arquivo / lista de texto

0

Eu tenho um arquivo de log que contém os pings de um determinado site em um arquivo de texto chamado pingoutput.txt, separando cada resposta de ping por linha. Agora eu preciso extrair deste arquivo de texto o tempo de ida e volta entre o tempo = e ms em qualquer outro arquivo de texto ou lista que eu poderia classificar do menor para o maior.

64 bytes from onofri.org (67.222.36.105): icmp_req=1 ttl=47 time=202 ms
64 bytes from onofri.org (67.222.36.105): icmp_req=2 ttl=47 time=206 ms
64 bytes from onofri.org (67.222.36.105): icmp_req=3 ttl=47 time=215 ms

Além disso, o arquivo pingout.txt é grande e tem cerca de 86.400 linhas. Eu estou fazendo isso através de um script de shell no linux.

    
por user192314 28.09.2016 / 14:23

8 respostas

2

Isso funciona para mim:

sed 's/.*time=\([0-9]*\) .*//' times | sort -n > outfile

Onde times é este arquivo:

cat times 
64 bytes from onofri.org (67.222.36.105): icmp_req=1 ttl=47 time=202 ms
64 bytes from onofri.org (67.222.36.105): icmp_req=2 ttl=47 time=206 ms
64 bytes from onofri.org (67.222.36.105): icmp_req=3 ttl=47 time=215 ms

E outfile é assim:

cat outfile 
202
206
215
    
por 28.09.2016 / 14:40
1

Você também pode usar regex Perl e grep

grep -oP '(?<=time\=).*' pingoutput 
    
por 28.09.2016 / 14:42
1

Você pode extrair o tempo com este exemplo de script:

awk -F\= '{print int($4)}' pingoutput.txt 

Ele usa = como delimitador e usa a função int para obter apenas os números da string "202 ms"

Para redirecionar a saída para outro comando de uso de arquivo:

awk -F\= '{print int($4)}' pingoutput.txt > times.txt

Para classificar a saída, você pode canalizar a saída do awk para ordenar o comando

awk -F\= '{print int($4)}' pingoutput.txt |sort -n > times.txt
    
por 28.09.2016 / 14:36
1

As principais ferramentas para esse tipo de trabalho são sed e awk . Eles são projetados para ler um pipe ou arquivo linha por linha e transformá-lo.

Exemplo de solução sed:

  sed 's/.* time=\([0-9]*\) ms//' pingoutput.txt 

A saída deve:

  202
  206
  215

Divisão do s/.* time=\([0-9]*\) ms// :

s significa que você quer fazer um comando de substituição. Comandos de substituição têm o padrão s/<pattern to match>/<replacement pattern>/ .

O <pattern to match> é .* time=\([0-9]*\) ms

O . é qualquer caractere. O * diz que qualquer caractere pode aparecer zero ou mais vezes. Isso é consumir todos os caracteres até a parte time= da linha.

A parte \( \) define o que é chamado de grupo. O que for correspondido pelo padrão entre os parênteses será classificado em um grupo chamado 1, já que há apenas um grupo em nosso padrão.

A parte dentro de \( \) é [0-9]* , que diz corresponder a qualquer caractere entre o caractere 0 e o caractere 9 (todos os dígitos) e novamente o * significa que pode haver zero ou mais . Isso corresponderá ao número em que você está interessado.

Finalmente, temos ms no final para consumi-lo da linha.

O <replacement pattern> é apenas ; Isso significa que você deseja substituir toda a string correspondente pelo que foi capturado pelo grupo 1 no padrão de correspondência.

Você pode fazer isso com awk também; Eu recomendo aprender a usar as duas ferramentas.

Adição:

Para ordenar o valor numericamente, você precisa transmitir os resultados usando o '|' na ferramenta de classificação. Mas, para ter certeza de que os horários estão ordenados numericamente, você deseja usar sort -n , caso contrário, você pode obter uma ordem de classificação estranha.

sed 's/.* time=\([0-9]*\) ms//' pingoutput.txt | sort -n

Adição adicional para suportar números decimais

sed 's/.* time=\([0-9]*\(\.[0-9]*\)\{0,1\}\) ms//' pingoutput.txt | sort -n

O que eu fiz foi adicionar uma parte opcional que descreve a parte decimal do número dentro do grupo que era \ ([0-9] * \) que adicionei:

O subgrupo Anther que pode aparecer 0 ou 1 vez apenas é descrito por \ (\) \ {0,1 \} a parte em {} o primeiro número é a ocorrência mínima do segundo número máximo. O padrão dentro desse grupo é \. [0-9] * a razão pela qual temos que fazer isso, mas a partir do '.' é de outra forma como você sabe agora '. significa qualquer caractere para que apenas permita um '.' você tem que escapar com \

    
por 28.09.2016 / 14:49
0

Se você tiver a opção pcre com grep

$ grep -oP 'time=\K\d+' pingout.txt 
202
206
215
$ grep -oP 'time=\K\d+' pingout.txt | sort -n
202
206
215
$ grep -oP 'time=\K\d+' pingout.txt | sort -nr
215
206
202
  • time=\K lookbehind positivo a string time= - isso não faz parte saída
  • \d+ um ou mais dígitos, também pode usar [^ ]+ para extrair caracteres que não sejam espaço

Para salvar a saída em um arquivo, use o redirecionamento >

$ grep -oP 'time=\K\d+' pingout.txt | sort -n > op.txt
$ cat op.txt 
202
206
215
    
por 28.09.2016 / 16:10
0
awk -F'[ =]' '{ print $11 }' logfile

Se 0 ms ping vezes nunca ocorrer, podemos "golf":

awk -F[\ =] '$0=$11'

Se houver uma coluna 11, $0 obterá um valor diferente de zero e não em branco. Esse valor é booleano verdadeiro, acionando a ação. A ação está ausente, portanto, a ação padrão é { print } , o que significa { print $0 } .

A expressão regular [ =] corresponde a um sinal de igual ou espaço e, com -F , instalamos isso como a variável FS : separador de campos do Awk. Cada linha de entrada é dividida em campos, removendo um espaço ou sinal de igual. Os campos são as partes da linha que permanecem ao redor destes separadores (mesmo que vazios: dois espaços consecutivos terão um campo entre eles). Sob essa separação, verifica-se que os tempos de ping terminam na 11ª coluna e, portanto, usamos o operador de acesso do parâmetro $ com o argumento 11 para se referir a ele.

Se ocorrerem zeros, ainda podemos jogá-lo no golfe:

awk -F[\ =] '$0=$11||1'

Se $0=$11 gerar zero / false, o lado direito do operador || (OR lógico) será avaliado e esse é o valor da expressão. Assim, garantimos que a expressão sempre seja verdadeira, de modo que a ação de impressão ocorra.

    
por 28.09.2016 / 17:32
-1
awk -F\= '{print int($4)}' test | sort -n  > t
    
por 28.09.2016 / 14:47
-1

Use o comando sed para extrair os campos relacionados. como

sed 's/.*time=\([0-9.]\+\).*//p' test.log |sort

$ cat test.log
PING 10.74.88.113 (10.74.88.113) 56(84) bytes of data.
64 bytes from 10.74.88.113: icmp_seq=1 ttl=59 time=0.326 ms
64 bytes from 10.74.88.113: icmp_seq=2 ttl=59 time=0.333 ms
64 bytes from 10.74.88.113: icmp_seq=3 ttl=59 time=0.322 ms
64 bytes from 10.74.88.113: icmp_seq=4 ttl=59 time=0.335 ms
64 bytes from 10.74.88.113: icmp_seq=5 ttl=59 time=0.337 ms
    
por 28.09.2016 / 14:42