grep padrão de regex corresponde a cada linha onde apenas todas as correspondências aparecem e são impressas na mesma linha

0

tentando extrair alguns padrões por linha, a partir de um arquivo de log. Estou tentando extrair o primeiro registro de data e hora e duas ou três outras correspondências, mas quero poder imprimir apenas as correspondências das linhas em que todas as correspondências aparecem. Existe um único comando grep com o qual eu posso fazer isso, ou eu tenho que percorrer cada linha?

Minha linha de registro é assim

2018-08-07 08:55:20 ERROR[t-dispatcher-24] - Error while processing message: code:[RequestTimeout], message:[{"from_addr_type": null, "transport_name": "999_abc_999_2_1", "in_reply_to": null, "group": null, "timestamp": "2018-08-07 07:55:19.795748", "from_addr": "341231231234", "message_type": "user_message", "helper_metadata": {}, "to_addr": "ABCD", "to_addr_type": null, "session_id": "157692", "content": "0013091779", "routing_metadata": {}, "message_version": "20110921", "transport_type": "XXXX", "provider": "abc_somewhere", "transport_metadata": {"abc_somewhere_XXXX": {"clientId": "XXXX157692", "starCode": "999", "session_id": "157692", "phase": "2", "dcs": "15", "requestId": "157692"}}, "session_event": "resume", "message_id": "5d9cab5353ff449783a737e8390a690b"}]

Eu quero ser capaz de extrair certos grupos como o timestamp no início, o "conteúdo" e "to_addr" seções.

Eu inventei isso: grep -oP '(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})|"to_addr":"\K(\d+)|"content":\K"(.+?)"' | tr -d '\n'

Mas não consigo selecionar apenas as linhas em que todas as três correspondências de padrão existem. Por favor, o que estou fazendo errado? Estou esperando muito?

    
por Sina 07.08.2018 / 10:02

1 resposta

0

Você está usando um OU | entre seus padrões, você quer um AND.

Em seu padrão, você está pesquisando "to_addr":"\K(\d+) , mas, por exemplo, o valor de to_addr é ABCD , portanto, não corresponde a \d+ e há um espaço entre "to_addr: e "ABCD" , mesmo para content .

Se to_addr for sempre antes de content :

grep -P '^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}.*?"to_addr": "\d+.*?"content": ".+?"' 

Ou então, use lookaheads:

grep -P '^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}(?=.*?"to_addr": "\d+)(?=.*?"content": "(.+?)")' 

Se você quiser imprimir apenas as correspondências, sugiro uma linha de uma linha Perl:

perl -ane 'print "$1\t$2\t$3\n" if (/^(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})(?=.*?"to_addr": "(\d+))(?=.*?"content": "(.+?)")/)' file
    
por 07.08.2018 / 10:29