Como extrair entre 2 strings quando o arquivo contém vários símbolos

0

Estou tentando extrair dados de formulário de um arquivo enorme. Eu preciso de um padrão muito específico que até agora me falha.
Eu tenho essa parte consistente do log:

Machine info and user info blah blah blah [senderID=60, 
ipaddress=/10.1.1.11:8443, serviceIdinList=[13], serviceBitbox=11111, 
servicesList= | BeatController | BeatMaker | WaveShow, client=apache, 

todas as linhas aparecem assim.
Dessa linha, preciso fazer com que pareça:

senderID=60, ipaddress=/10.1.1.11:8443, serviceIdinList=[13], 
serviceBitbox=11111, servicesList= | BeatController | BeatMaker | WaveShow,  

* Nota, tudo após o "WaveShow," é irrelevante, como é tudo antes de "senderID"

Eu tentei este comando de um post aqui,

sed -n '/servicesList=/{s/.*servicesList=//;s/\S*=.*//;p}'

mas apenas imprime

servicesList= | BeatController | BeatMaker | WaveShow

Eu tentei modificá-lo em algumas iterações com regex, jogado com grep e sed mas sem progresso. por favor ajude :)

    
por dtuaev25 14.11.2018 / 11:14

2 respostas

0

Se o que você está tentando fazer é exibir tudo entre e incluindo senderID= e WaveShow, , você precisa deste comando sed :

sed -n 's/.*\(senderID=.*WaveShow,\).*//p'

Isso capturará tudo entre essas duas strings usando os colchetes \( e \) e a saída usando (e etc., se você tiver mais capturas).

Observe que o .* principal é "ganancioso", o que significa que se você tiver a string senderID= duas vezes na entrada, a primeira será descartada. Se isso não é o que você quer, então sed não é a ferramenta correta; perl pode lidar com isso. O comando então se torna:

perl -ne 'print if s/.*?(senderID=.*WaveShow,).*/$1/'

-n significa "executar um loop para cada linha de entrada e não imprimir a linha no final do loop". -e especifica a expressão a ser executada dentro do loop.

O ? após o .* altera o * para corresponder o mínimo possível (ou seja, corresponde de forma não voraz). Os colchetes fazem o perl agrupar essa parte e capturá-la, o que pode ser usado como $1 para a primeira captura, $2 para a segunda, etc.

No entanto, essa não é a maneira ideal de fazer isso em perl. Isso é muito melhor, pois não envolve a mudança desnecessária de strings, capturando o texto e imprimindo exatamente isso:

perl -ne 'print "$1\n" if /(senderID=.*WaveShow,)/'

Provavelmente existem muitas outras maneiras de fazer isso no perl, talvez até de maneira mais eficiente.

    
por 14.11.2018 / 13:15
0

A vírgula final é necessária?

Se não, isso deve funcionar:

grep senderID filename | cut -d '[' -f 2- | cut -d ',' -f -5

Saída:

senderID=60, ipaddress=/10.1.1.11:8443, serviceIdinList=[13], serviceBitbox=11111, servicesList= | BeatController | BeatMaker | WaveShow

    
por 14.11.2018 / 13:08