Comando Bash para contar líneas con subcadenas coincidentes en dos posiciones diferentes

Comando Bash para contar líneas con subcadenas coincidentes en dos posiciones diferentes

Estoy intentando obtener algunas estadísticas triviales sobre algunos resultados de depuración.

Cada línea de depuración tiene la forma(class name)(delimiter 1)(object ID)(delimiter 2)(method name)(delimiter 3)(log message)

Quiero contar cuántas líneas provienen de qué métodos.

Básicamente, si cada línea se puede reducir a (class name)(delimiter)(method name), quiero saber cuántas apariciones de cada una de esas reducciones aparecen en el archivo de registro.

¿Qué comando puedo ejecutar en Bash para realizar el conteo?

(Estoy haciendo esto en macOS con macports reemplazando la mayoría de las herramientas predeterminadas de estilo BSD con herramientas GNU).

Puedo extraer el nombre de la clase con grep -o -E "^.*(delimiter 1), extraer el nombre del método con grep -o -E "(delimiter 2).*(delimiter 3)", o resaltar ambos con grep --color=always -E "^.*(delimiter 1)|(delimiter 2).*(delimiter 3)". Me quedé atascado buscando una manera de grepgenerar solo las dos coincidencias que luego podrían ejecutarse | uniq -cpara realizar el conteo.

¿Hay alguna manera de imprimir grepambas coincidencias para cada línea en lugar de solo una coincidencia o la línea completa?

Respuesta1

En esencia, se puede hacer con

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 deaquí)

  • .*puede coincidir demasiado; sedes codicioso y quiere hacer coincidir tanto como sea posible lo antes posible, por lo que es posible que deban ser, por ejemplo, negaciones de los delimitadores (lo que puede ser complicado si tiene delimitadores inconvenientes)
  • Pasar de ^a $es importante; si su expresión no coincide, toda la línea sedincluirá la parte no coincidente en la salida.
  • Los paréntesis sólo son necesarios alrededor del nombre de la clase y del método; eliminar los demás significa cambiar los números al final, porque los números se refieren a subexpresiones entre paréntesis en orden. (Incluirlos a todos hace posible mostrar más de lo que sucede en la sedsalida, por ejemplo, cambiando el final a /\1(delimiter)\5 -- \1\2\3\4\5\6\7/p)
  • sortdebe ejecutarse antes uniq -cporque uniq -csolo cuenta las ejecuciones de líneas idénticas consecutivas, las líneas idénticas no consecutivas obtienen recuentos separados
  • uniq -cno se puede reemplazar sort -uporque sort -usolo descarta duplicados, no los cuenta
  • El final sortno es necesario para responder la pregunta tal como se hizo.
  • Sí, si usas expresiones regulares para resolver un problema, ahora tienes dos problemas.

información relacionada