Como posso usar o sed\awk para procurar determinadas linhas em um arquivo e, em seguida, combinar todas as linhas subsequentes que correspondam a um padrão diferente?

Como posso usar o sed\awk para procurar determinadas linhas em um arquivo e, em seguida, combinar todas as linhas subsequentes que correspondam a um padrão diferente?

Encontrei um tópico semelhante, mas não consegui descobrir como implementá-lo para meu próprio uso:

pegue várias linhas após uma linha de destino correspondente

Aqui está o problema:

Estou tentando implementá-lo em um projeto próprio, mas não consigo fazê-lo funcionar. Estou usando Linux, alguém pode decompô-lo?

Basicamente, o que estou tentando fazer é passar por um pacote de log e capturar linhas específicas junto com sua pilha/detalhes. Aqui está um exemplo:

2020-01-20T05:58:19.119Z verbose vpxa[6E21B70] [Originator@6876 sub=PropertyProvider opID=k5cokp1a-928316-auto-jwal-h5:70047736-92-01-84] [CommitChangesAndNotify] Updating cached values
2020-01-20T05:58:19.119Z info vpxa[6E21B70] [Originator@6876 sub=Default opID=k5cokp1a-928316-auto-jwal-h5:70047736-92-01-84] [VpxLRO] -- ERROR task-107599 -- **vm-1178** -- vim.VirtualMachine.reconfigure: vmodl.fault.InvalidArgument:
--> Result:
--> (vmodl.fault.InvalidArgument) {
-->    faultCause = (vmodl.MethodFault) null,
-->    faultMessage = (vmodl.LocalizableMessage) [
-->       (vmodl.LocalizableMessage) {
-->          key = "msg.disk.extendFailure",
-->          arg = (vmodl.KeyAnyValue) [
-->             (vmodl.KeyAnyValue) {

Desejo capturar todas as linhas que contêm "vm-1178" e todas as linhas subsequentes que começam com "-->" até que o padrão mude e, em seguida, começar a procurar por vm-1178 até a próxima vez que isso ocorrer, etc.

Espero que faça sentido. Obrigado!

Responder1

Tente isso,

awk '!/^-->/{p=0} /vm-1178/{p=1} p'
  • !/^-->/{p=0}: Defina var p(como print) como 0 sempre que a linha não começar com -->.
  • /vm-1178/{p=1}: Defina var p= 1 sempre que a linha corresponder /vm-1178/.
  • p: Imprima a linha sempre que pfor verdade (aqui = 1)

Responder2

Você poderia usar awkpara esse fim:

awk 'index($0,"vm-1178")>0 {in_pat=1; print; next} \
in_pat == 1 && $0 ~ /^-->/ {print; next} \
{in_pat=0}' logfile.txt

Ele contém três regras:

  • A primeira regra irá procurar linhas contendo o padrão e imprimi-las, além de definir um sinalizador interno in_patcomo 1.
  • A segunda regra afirma que todas as linhas subsequentes começando com -->também serão impressas.
  • A terceira regra é usada para redefinir esse sinalizador na primeira linhanãocontendo o padrão ou não começando com a -->, para que nada seja impresso até que o padrão seja encontrado novamente.

Observe que na primeira regra, a indexfunção é usada em vez de uma correspondência RegExp. Isso ocorre para que você também possa procurar padrões contendo caracteres que tenham um significado especial em expressões regulares.

Responder3

Usando perl, isso funcionaria:

 perl -ne ' { $t=0 if ( !/^-->/ ); $t=1 if(/vm-1178/); print if($t); }' <filename>

informação relacionada