Como cortar um segmento ou vários segmentos de uma linha?

1

Aqui está uma linha de logs de amostra

03 Jun 2017/13:51:32:553 DEBUG connectors.BaseConnector [] [] [] - Request Message is <soapenv:Envelope xmlns:_0="abc" xmlns:_1="abcd" xmlns:soapenv="abcde" xmlns:v1="abcdef"><soapenv:Header><_0:Trace mustUnderstand="false"></_0:Trace><_0:MsgDetl mustUnderstand="false"><_0:MsgUID>20150103135132968917</_0:MsgUID></_0:MsgDetl><_0:ExtendedHeader><CredentialsRqHdr><PartyId>123456789</PartyId><LoginName>Userid</LoginName><PartyAuth><SecTokenKey><SessKey>SessionID</SessKey></SecTokenKey></PartyAuth></CredentialsRqHdr></_0:ExtendedHeader></soapenv:Header><soapenv:Body><v1:actionList><_1:CommonRq><_1:OrgCode>2009</_1:OrgCode></_1:CommonRq><_1:CustId>12345678</_1:CustId><v1:e123><v1:SortOrder>L</v1:SortOrder><v1:SortSeq>D</v1:SortSeq></v1:e123></v1:actionList></soapenv:Body></soapenv:Envelope>

As palavras-chave são MsgUID , LoginName , CustId e a posição não é fixa. Eu quero saída é como abaixo:

03 Jun 2017/13:51:32:553 MsgUID, LoginName, CustId
    
por Kong 21.07.2017 / 12:37

2 respostas

0

Eu usaria sed para isso:

sed 's/\(.*:[0-9]* \).*<_0:MsgUID>\([^<]*\).*/, /'

para o registro de data e hora e MsgUID. Você pode expandi-lo facilmente para incluir LoginName e CustId também: Forme expressões regulares para corresponder a essas partes e coloque as partes que deseja manter em \(\) . Na cadeia de substituição, você pode reutilizar essas partes como ' for the first, \ 2 for the second and so on. Try to solve it by understanding the expession for MsgUID '. Se você não conseguir, poste seu código na pergunta.

    
por 21.07.2017 / 13:01
1

Usando o GNU sed , você pode fazer isso como:

sed -Ee '
   s/^/\n\n/
   s/\n\n/&\n/;s/[[:blank:]]+/\n/3;s/(.*)\n\n(.*)\n(.*)\n/\n\n/
   s|<_0:MsgUID>|\n|;s|</_0:MsgUID>|\n|;s/(.*)\n\n(.*)\n(.*)\n/ \n\n/
   s|<LoginName>|\n|;s|</LoginName>|\n|;s/(.*)\n\n(.*)\n(.*)\n/ \n\n/
   s|<_1:CustId>|\n|;s|</_1:CustId>|\n|;s/(.*)\n\n(.*)\n(.*)\n/ \n\n/
   s/\n\n.*//
' log.file

Explicação

  • Colocamos um marcador, \n\n , no início da linha. Todas as correspondências encontradas na linha são lançadas para a esquerda deste marcador.
  • Primeiro, isolamos a parte da data e, em seguida, movemo-la para a esquerda do marcador.
  • Em todas as etapas subsequentes, isolamos as tags de interesse e lançamos os valores da tag à esquerda do marcador.
  • Quando terminamos, simplesmente apagamos tudo à direita do marcador, incluindo o marcador, e o que resta no espaço padrão é o que queremos.
  • Observação: esse método é extensível para incluir quantas tags forem necessárias.

Resultados

03 Jun 2017/13:51:32:553 20150103135132968917 Userid 12345678

Outra maneira é usar os regexes Perl:

perl -lne '$,=$";
print /^(?:\S+\s+){2}\S+|<(?:_0:MsgUID|LoginName|_1:CustId)>\K(?:.*?)(?=<)/g' log.file

Aqui, definimos a OFS $, para $" , que é space . O perl regex /..../g produzirá todas as correspondências não parecidas em uma lista, que então será o espaço impresso separado devido ao valor do OFS já estabelecido.

    
por 21.07.2017 / 15:32