Comando Bash para contar linhas com substrings correspondentes em duas posições diferentes

Comando Bash para contar linhas com substrings correspondentes em duas posições diferentes

Estou tentando obter algumas estatísticas triviais sobre alguma saída de depuração.

Cada linha de depuração tem o formato(class name)(delimiter 1)(object ID)(delimiter 2)(method name)(delimiter 3)(log message)

Quero contar quantas linhas vêm de quais métodos.

Essencialmente, se cada linha puder ser reduzida para (class name)(delimiter)(method name), quero saber quantas ocorrências de cada uma dessas reduções aparecem no arquivo de log.

Qual comando posso executar no Bash para fazer a contagem?

(Estou fazendo isso no macOS com macports substituindo a maioria das ferramentas padrão do estilo BSD por ferramentas GNU.)

Posso extrair o nome da classe com grep -o -E "^.*(delimiter 1), ou extrair o nome do método com grep -o -E "(delimiter 2).*(delimiter 3)", ou destacar ambos com grep --color=always -E "^.*(delimiter 1)|(delimiter 2).*(delimiter 3)". Fiquei preso procurando uma maneira de grepproduzir apenas as duas partidas que poderiam ser analisadas | uniq -cpara fazer a contagem.

Existe uma maneira de grepimprimir ambas as correspondências para cada linha, em vez de apenas uma correspondência ou a linha inteira?

Responder1

Em essência, isso pode ser feito com

sed -r -n 's/(^.*)(delimiter 1)(.*)(delimiter 2)(.*)(delimiter 3)(.+$)/\1(delimiter)\5/p' <( command that generates debug logs ) | sort | uniq -c | sort -rn

(adaptado deaqui)

  • .*pode combinar demais; sedé ganancioso e deseja combinar o máximo possível o mais cedo possível, portanto, talvez seja necessário, por exemplo, negações dos delimitadores (o que pode ser complicado se você tiver delimitadores inconvenientes)
  • Ir de ^para $é importante, se sua expressão não corresponder à linha inteira, sedincluirá a parte sem correspondência na saída
  • Parênteses são necessários apenas em torno do nome da classe e do método; remover os outros significa alterar os números no final, porque os números se referem a subexpressões entre parênteses em ordem. (Incluir todos eles torna possível mostrar mais do que está acontecendo na sedsaída, por exemplo, alterando o final para /\1(delimiter)\5 -- \1\2\3\4\5\6\7/p)
  • sorttem que ser executado antes uniq -cporque uniq -capenas conta execuções de linhas idênticas consecutivas, linhas idênticas não consecutivas obtêm contagens separadas
  • uniq -cnão pode ser substituído sort -uporque sort -uapenas descarta duplicatas e não as conta
  • A final sortnão é necessária para responder à pergunta feita
  • Sim, se você usa expressões regulares para resolver um problema, agora você tem dois problemas.

informação relacionada