Extraindo dados específicos de um arquivo usando a palavra-chave [awk]

1

Eu tenho um arquivo complicado, que é assim:

configuration {
  step        58000
  dt 2.00000000000000e+00
}

colvar {
  name r
      x  1.44869849559022e+01
}

0.00000000000000e+00 0.00000000000000e+00 0.00000000000000e+00
0.00000000000000e+00 0.00000000000000e+00 0.00000000000000e+00

hill {
  step         1440
  weight    1.00000000000000e-01
  centers   1.47455750990065e+01 -1.69229380745887e+02
  widths    1.25331413731550e+00  1.25331413731550e+00
}
hill {
  step         1560
  weight    1.00000000000000e-01
  centers   1.47435719215456e+01 -1.70289673373179e+02
  widths    1.25331413731550e+00  1.25331413731550e+00
}
hill {
  step         1680
  weight    1.00000000000000e-01
  centers   1.47427376221419e+01 -1.68774767870364e+02
  widths    1.25331413731550e+00  1.25331413731550e+00
}  

Estou interessado em extrair etapas, peso e larguras desse arquivo e gravá-las em um novo arquivo de saída com uma separação de separadores. Apenas assim: -

#!step   width1                    width2             weight
1440   1.25331413731550e+00  1.25331413731550e+00   1.00000000000000e-01

Eu tenho o seguinte, que apenas grava etapas e peso: -

awk ' b ~ /hill/ && a ~ /step/ && /weight/ {print v"\t"$2}{b=a;  a=$0; v=$2}' input > output

Como posso estendê-lo para escrever larguras também?

    
por Vikas Dubey 03.02.2017 / 08:09

4 respostas

1

você pode usar a função getline que lê na linha seguinte.

$ awk -vOFS='\t' '/^hill {/{ 
    getline; st=$2
    getline; we=$2
    getline; getline; wd1=$2; wd2=$3
    print st, we, wd1, wd2
}' file
1440    1.00000000000000e-01    1.25331413731550e+00    1.25331413731550e+00
1560    1.00000000000000e-01    1.25331413731550e+00    1.25331413731550e+00
1680    1.00000000000000e-01    1.25331413731550e+00    1.25331413731550e+00
    
por 03.02.2017 / 08:46
1

A seguinte solução é expandida por uma questão de clareza:

 awk '/hill/   { delete data }
      /step/   { data["step"] = $2 }
      /weight/ { data["weight"] = $2 }
      /widths/ { data["widths"] = $2 "\t" $3;
                 print data["step"] "\t" data["weight"] "\t" data["widths"]; }' input
    
por 03.02.2017 / 08:45
1

Analisando seu arquivo de entrada com este comando de uma linha:

echo -e "step\twidth1\t\t\twidth2\t\t\tweight" && grep -A4 ^hill widwei.txt | grep "step\|weight\|widths" | awk '{$1=""; print $0}' | awk 'NR%3{printf $0"";next;}1' |  awk ' { t = $3; $3 = $2; $2 = t; print; } ' | awk ' { t = $4; $4 = $3; $3 = t; print; } '  | sed -e 's/^ //g' | sed -e 's/ /\t/g'
  1. Imprimir o cabeçalho
  2. Pegue as próximas 4 linhas para a seção de colinas.
  3. Pegue os valores de etapa, peso e largura.
  4. Imprima-os em uma linha.
  5. Troque as colunas para obter o formato desejado.
  6. Exclua os espaços iniciais restantes e separe-os com guias.
por 03.02.2017 / 09:11
1
awk -v RS="hill {"    'NF==11 {$1=$3=$5=$8=$11=""; print }' file

(usando o gnu awk; embora seja facilmente adaptável, esta solução não é robusta para formatar variações)

  • -v RS="hill {" define um novo separador de registro (RS) (por padrão era linhas, agora são parágrafos "hill")
  • NF==11 ... se o recors tiver 11 campos
  • $1=$3=$5=$8=$11=""; ... remover os literais
  • print ... e imprima o lembrete
por 03.02.2017 / 10:07

Tags