awk '/10:..:/, /13:..:/' server.log > /tmp/awktmp
Eu tentei este comando como alguém me deu. Funcionou para mim encontrar logs entre 10:00 e 13:00, mas não entendo completamente.
Por favor, diga-me uma solução elegante, se você tiver um. Lembre-se de que os servidores remotos são mínimos e não possuem utilitários avançados.
O que eu não entendo aqui é'/10:..:/, /13:..:/'
- Eu entendo
10:..
que significa10
e:
corresponde exatamente a 2 dígitos. - Mas o que
:
significa outro?
Suponho que as barras sejam para colocar expressões regulares como fazemos no JavaScript regex. Não tenho 100% de certeza sobre isso.
Atualização 1:
A hora está na segunda coluna, no formatoHH:MM:SS
Atualização 2:
sed -n -e '/8:..:../,/9:..:../p' application.log > /tmp/sedtmp
Eu tentei isso, mas isso também está mostrando logs de arquivos 07:57:47
.
Atualização 3
Os logs nem sempre contêm o carimbo de data/hora em cada linha. Algumas linhas não contêm nenhum carimbo de data/hora. Como você superou esse problema? Eu estupidamente usei awk e perdi todas as linhas que não tinham valor de tempo nelas. Existe uma maneira de evitar esse problema?
Assim é o que quero dizer.
2023-08-07 09:20:35 0123456789 INFO CustomerLogoutResource:95 - Entering logout api.
2023-08-07 09:20:35 0123456789 ERROR AppExceptionMapper:87 - Exception has been thrown by container
2023-08-07 09:20:35 0123456789 ERROR AppExceptionMapper:555 - Unchecked Exception
java.lang.NullPointerException
at NullPointerExceptionExample.printLength(NullPointerExceptionExample.java:3)
at NullPointerExceptionExample.main(NullPointerExceptionExample.java:8)
O padrão
/10:..:/
corresponde aos dígitos 10, dois separadores de:
e quaisquer dois caracteres entre eles. Portanto, corresponderá a um horário (em qualquer lugar na linha de entrada) como10:35:22
. Mas também corresponderia a uma linha contendoThis10:ZZ:Camels
, portanto, não é um teste muito bom.Um padrão melhor pode ser
/10:[0-5][0-9]:[0-5][0-9]/
, que verifica se os minutos e segundos estão no intervalo de 00 a 59. Mas também pode ser útil verificar se os horários estão em um campo específico, ou se há espaços em branco ao redor, ou se estão (inclusive) próximos ao início do registro. Você pode postar algumas linhas de entrada de amostra para que possamos dizer melhor o que é necessário.Ter dois padrões separados por uma vírgula "liga" a correspondência quando o primeiro padrão é detectado e "desliga" a correspondência quando o segundo padrão é detectado. Ele corresponderá a todas as linhas entre esses eventos (inclusive), mesmo que não contenham nenhuma data.
Isso é muito diferente do padrão único
/1[0-2]:[0-5][0-9]:[0-5][0-9]/
, que corresponderia apenas a linhas individuais entre 10:00:00 e 12:59:59, em qualquer ordem em que estivessem.Esse tipo de abordagem falha em encontrar as linhas para
11:00
se13:00
não houver log entre 10:00 e 11:00 e relataria todas as linhas depois14:00
se não houvesse log entre 13:00 e 14:00 (e havia pelo menos um entre 10 e 11).O melhor para esse tipo de coisa é fazer comparação lexical do tempo contra os limites.
Por exemplo, se a hora estiver no terceiro campo:
Se você não sabe onde está a hora na linha, você pode fazer:
Ou:
Aqueles relatam as linhas que possuem um carimbo de data/hora no intervalo. Se você tiver linhas sem carimbos de data/hora entre as linhas com carimbos de data/hora e quiser que sejam relatados, poderá usar a
beginning-condition, end-condition {action}
abordagem como na sua pergunta, mas novamente usar a comparação em vez da correspondência regex ou fazer a troca de estado manualmente para continuar excluindo o limite superior :o padrão awk:
será verdadeiro desde a primeira linha correspondente a regA, até a primeira linha correspondente a regB. E, como sempre, quando algo corresponde a uma expressão: se não houver
{ actions }
após a expressão para especificar quais ações executar quando corresponder, a ação padrão é: imprima a linha onde a expressão é verdadeira.Agora eles escolheram:
para ter (um pouco) mais certeza de que você corresponde a 10:mm:ss e não a hh:10:ss. (Eles fazem isso assumindo que qualquer citação de hora será : hh:mm:ss, e que não há ':' antes da hora ... isso nem sempre é verdade, dependendo do formato de data usado. E como dito nos comentários, também pode combinar com outras coisas.
Se você sabe que o início das linhas é sempre:
Você pode combinar mais de perto com:
e certifique-se de corresponder apenas a partir do início (^) da linha e não onde quer que essas coisas possam aparecer na linha.
Aqui está uma solução possível que seleciona logs entre dois timestamps em um arquivo de log. Este script supõe que o arquivo de log tenha colunas separadas por espaços e a segunda coluna contém o carimbo de data/hora no formato
HH:MM:SS
. Pode não ser o mais elegante, mas pelo menos é legível.-F" "
define o separador de campo como um caractere de espaço.$2
refere-se ao segundo campo em cada linha do arquivo de entrada (os campos são separados por espaços neste caso).>= "09:00:00"
verifica se o valor do segundo campo é maior ou igual a "09:00:00".&&
um operador lógico que combina condições. Significa "e"$2 <= "12:00:00"
verifica se o valor do segundo campo é menor ou igual a "12:00:00".sever.log
é o seu arquivo de entradaVerificação da solução
Para um
server.log
que se parece com isto:Saída: