Lendo linhas específicas do arquivo de entrada

0

Eu tenho um arquivo de entrada com essa estrutura geral. Eu só quero extrair os valores step e weight dos blocos de hill e colocá-los em um arquivo de saída usando awk / sed / grep. Os blocos das colinas são organizados de maneira semelhante em todo o arquivo de entrada.

Editar: Eu estou usando o MAC OSX.

 configuration {
 step         5000
 dt 2.000000e+00
 }

colvar {
name d1
x  1.70882305580118e+01
v  0.00000000000000e+00
}

1.85104129628346e-02 9.71380137561312e-02 4.00538287370335e-02
1.25662994200839e-02 9.88655406140091e-02 1.41657757894898e-01

hill {
step            0
weight    1.00000000000000e-01
centers   1.23563844380284e+02
widths    1.25331413731550e+00
}
 hill {
 step          100
 weight    1.00000000000000e-01
centers   1.19065310650377e+02
widths    1.25331413731550e+00
}

Através de algumas outras respostas eu consegui encontrar alguma ajuda: -

 sed 's/^.*weight//' diol_colvar.colvars.state > hill.txt
 sed 's/^.*step//' diol_colvar.colvars.state > hill.txt

Infelizmente, isso não está funcionando como eu queria.

Eu quero minha saída algo assim: -

  0     1.00000000000000e-01
  100   1.00000000000000e-01

Por favor me ajude a resolver esse problema.

Obrigado,

    
por Vikas Dubey 03.09.2016 / 10:50

2 respostas

1

1) Com sed

Supondo que step e weight ocorram em linhas consecutivas,

$ sed -nE '/step/{N;s/.*step\s+(\S+).*\n.*weight\s+(\S+).*/\t/p}' ip.txt 
0   1.00000000000000e-01
100 1.00000000000000e-01
  • -nE não imprime linhas por padrão e usa regex estendido
  • /step/ corresponde se as linhas contiverem step
  • N para obter a próxima linha

Nota:

O acima foi testado em GNU sed 4.2.2 . O abaixo pode ajudar no OS X e outras versões. Veja este Q & A sobre SO para detalhes, ponto principal sendo \s pode não funcionar da mesma forma que o GNU sed

sed -nE '/step/{N;s/.*step[[:space:]]+([^[:space:]]+).*\n.*weight[[:space:]]+([^[:space:]]+).*/\t/p}' ip.txt

2) Com awk

$ awk 'a ~ /step/ && /weight/{print v"\t"$2} {a=$0; v=$2}' ip.txt 
0   1.00000000000000e-01
100 1.00000000000000e-01
  • {a=$0; v=$2} salva a linha e o segundo campo
  • a ~ /step/ && /weight/ corresponde se a linha anterior contém step e a linha atual contém weight

Supondo que os blocos hill sejam todos semelhantes à entrada fornecida, podemos combinar três linhas consecutivas para restringir a correspondência apenas a hill blocks

awk 'b ~ /hill/ && a ~ /step/ && /weight/{print v"\t"$2} {b=a; a=$0; v=$2}' ip.txt

Para salvar os resultados, adicione > output_filename ao fim do comando

Referência:

por 03.09.2016 / 11:47
0

Mais fácil de usar o awk duas vezes: a primeira vez para extrair o hill { } de bloco e o segundo para extrair os valores de etapa / peso.

awk '/hill *{/,/}/ {print}' \
   | awk '$1 == "step" { st = $2 }; $1 == "weight" { print st "\t" $2}'

Este comando funcionará somente se weight vier após step mas não for necessário em linhas consecutivas.

    
por 03.09.2016 / 15:15

Tags