awk from different lines

2

Eu estou tentando extrair alguns dados de um arquivo que está constantemente atualizando e eu descobri como filtrar duas seqüências de caracteres com o grep. A saída é a seguinte:

!    total energy              =   -9744.24963670 Ry
     convergence has been achieved in 188 iterations
!    total energy              =   -9744.30001681 Ry
     convergence has been achieved in 140 iterations
!    total energy              =   -9744.33953891 Ry
     convergence has been achieved in 155 iterations
!    total energy              =   -9744.36584201 Ry
     convergence has been achieved in 164 iterations
!    total energy              =   -9744.37925372 Ry
     convergence has been achieved in 154 iterations
!    total energy              =   -9744.39185493 Ry
     convergence has been achieved in 153 iterations
!    total energy              =   -9744.39836617 Ry
     convergence has been achieved in 160 iterations

Agora, o que eu gostaria de fazer é extrair dessas linhas os números da seguinte forma: da linha que começa com! Eu quero o número na coluna n º 5 e da próxima linha na saída do grep eu quero o número na coluna n º 6. Em seguida, gostaria que esses números fossem gravados em um arquivo separado como duas colunas separadas como:

188 -9744.24963670
140 -9744.30001681
155 -9744.33953891
164 -9744.36584201

Eu estava pensando que uma abordagem com o awk fazendo um loop em todos esses resultados do grep e depois examinando linhas numeradas ímpares e imprimindo a coluna 5 e depois linhas pares imprimia a coluna 6. Mas não tenho idéia de como fazer isso.

Eu tentei extrair resultados individuais em variáveis separadamente:

var1=$(grep '!' input.file | awk '{print $5}')

e

var2=$(grep 'convergence has been achieved' input.file | awk '{print $6}')

e depois tentei escrevê-los em um arquivo como:

echo $var1 $var2 > data.dat

No entanto, o resultado não é o esperado:

188                                                                                                                                                                                             
140
155
164
154
153
160 -9744.24963670
-9744.30001681
-9744.33953891
-9744.36584201
-9744.37925372
-9744.39185493
-9744.39836617

Eu não sei como escrevê-los na forma que mencionei acima. Além disso, uma vez que o arquivo é constantemente atualizado, eu imagino o pedaço de código a ser combinado com um loop while até a condição final (eu sei como fazer esta última parte)

Espero ter explicado isso com clareza!

    
por lucian 17.11.2017 / 11:45

2 respostas

2
Solução

awk :

awk 'v && NR==n{ print $6,v > "result.txt" }/^!/{ v=$5; n=NR+1 }' file
  • <condition1> { <statement> ... }<condition2>{ <statement> ... } - as condições com as respectivas declarações serão avaliadas consecutivamente

  • /^!/{ v=$5; n=NR+1 } - ao encontrar a linha que começa com ! - capture o quinto valor do campo $5 e planeje o próximo número de linha NR+1 (atribuindo à variável n )

  • v && NR==n - se tivermos o primeiro número crucial v e o número atual do registro NR é o necessário "próximo número da linha" n - imprima os valores no arquivo result.txt

O conteúdo do arquivo result.txt :

188 -9744.24963670
140 -9744.30001681
155 -9744.33953891
164 -9744.36584201
154 -9744.37925372
153 -9744.39185493
160 -9744.39836617
    
por 17.11.2017 / 11:58
1

Com sua própria solução, você precisa ter o comando paste para imprimir lado a lado os resultados.

paste <(echo "$var2") <(echo "$var1") #or better via 'printf'
paste <(printf '%s' "$var2") <(printf '%s' "$var1")

Mas com o comando awk simples, basta fazer:

awk '/\!/{C5=$5;getline; print $6, C5 >"output.txt"}' infile
    
por 17.11.2017 / 11:51