Retornando apenas a parte de uma linha após um padrão correspondente (Unix)

1

Eu tenho uma pasta pai (abeps) que contém várias subpastas (1,2,3 .... 25) onde o arquivo de saída está localizado, um no qual - todos são o mesmo nome (opt.out). Nesses arquivos há uma saída imprevisível. Este é um exemplo de uma linha que preciso filtrar:

A\HF=-1378.9118397\RMSD=4.560e-09\RMSF=1.758e-05\Dipole=0.2110167,0.39

ou

978,3.8529967641,3.6669041122\Version=ES64L-G09RevD.01\State=1-A\HF=-

então a coisa é que estou interessado em obter tudo entre \ HF = e até \

Mas eles podem estar em linhas diferentes, e até mesmo o HF pode estar em linhas diferentes, então o grep não vai pegá-lo. Então eu tentei escrever o resultado em um arquivo:

grep 'HF=-' abeps/*/opt.out > data

e como resultado, obtenha isso

abeps/10/opt.out: 1-A\HF=-1378.9114895\RMSD=5.126e-09\RMSF=5.036

abeps/12/opt.out: \State=1-A\HF=-1378.9185518\RMSD=2.940e-09\RMSF

abeps/13/opt.out: 33413\Version=ES64L-G09RevD.01\State=1-A\HF=-137

    
por Maxim Galkin 26.05.2014 / 17:43

3 respostas

2

Se a sua versão do grep for compatível com o PCRE (expressões regulares compatíveis com Perl), você poderá usar os recursos lookbehind e lookahead do Perl

grep -oPz '(?<=\HF=)(.|\n)+?(?=\)'

ou com pcregrep (se disponível)

pcregrep -Mo '(?<=\HF=)(.|\n)+?(?=\)'

Lembre-se de que, se o seu padrão de interesse for realmente dividido por linhas, o texto retornado reterá a nova linha - talvez você queira retirá-lo com tr ou sed antes de usar o resultado.

Se o texto em si não puder ser dividido em linhas (somente os marcadores \HF e \ ), você poderá substituir (.|\n)+? pelo mais simples .+? , ou seja,

grep -oPz '(?<=\HF=).+?(?=\)'

Se mesmo o marcador \HF= puder ser dividido em qualquer ponto por uma nova linha (conforme indicado pelo seu comentário na postagem original), será necessária uma abordagem ligeiramente diferente, pois o PCRE não suporta atualmente lookbehinds de comprimento variável. Nesse caso, você pode tentar

grep -oPz '\\n?H\n?F\n?=\K(.|\n)+?(?=\)'

onde o lookbehind é substituído por uma expressão pseudo-âncora usando \K

    
por 26.05.2014 / 18:37
1

Você também pode usar sed ,

sed -r '/.*HF=([^\]*)\?.*/s///g' file

Exemplo:

$ echo 'A\HF=-1378.9118397\RMSD=4.560e-09\RMSF=1.758e-05\Dipole=0.2110167,0.39' | sed -r '/.*HF=([^\]*)\?.*/s///g'
-1378.9118397

$ echo '978,3.8529967641,3.6669041122\Version=ES64L-G09RevD.01\State=1-A\HF=-' | sed -r '/.*HF=([^\]*)\?.*/s///g'
-
    
por 26.05.2014 / 18:58
1

Com o recente pcregrep :

pcregrep -Mo1 '(?s)\HF=(.*?)\'
    
por 26.05.2014 / 22:50

Tags