Estou tentando obter dados de um arquivo que é assim:
6 6 1 0
0.1166667E+02 0.4826611E-09 0.4826611E-09 0.3004786E-09 0.5000000E-15
1.000000000000000E-004
CAR
system-001
10.51965443 -34.96542345 301 1.95329810 1.00000000
-15.558 0.1631E+01 0.1597E+02
-15.407 0.1661E+02 0.1779E+02
-15.255 0.4253E+01 0.1990E+02
-15.104 0.0000E+00 0.2000E+02
-14.952 0.0000E+00 0.2000E+02
-3.884 0.0000E+00 0.2000E+02
-3.732 0.0000E+00 0.2000E+02
-3.581 0.0000E+00 0.2000E+02
-3.429 0.0000E+00 0.2000E+02
-3.277 0.8214E-03 0.2000E+02
-3.126 0.3543E+00 0.2002E+02
1.726 0.1019E+01 0.4386E+02
1.877 0.5581E+00 0.4399E+02
2.029 0.0000E+00 0.4400E+02
2.181 0.0000E+00 0.4400E+02
2.332 0.0000E+00 0.4400E+02
2.484 0.0000E+00 0.4400E+02
2.636 0.0000E+00 0.4400E+02
2.787 0.0000E+00 0.4400E+02
2.939 0.0000E+00 0.4400E+02
3.090 0.0000E+00 0.4400E+02
3.242 0.0000E+00 0.4400E+02
3.394 0.0000E+00 0.4400E+02
3.545 0.0000E+00 0.4400E+02
3.697 0.0000E+00 0.4400E+02
3.849 0.0000E+00 0.4400E+02
4.000 0.0000E+00 0.4400E+02
4.152 0.6271E-01 0.4400E+02
4.303 0.4520E+01 0.4433E+02
4.455 0.5040E+01 0.4511E+02
Eu quero pegar sempre a quarta coluna da linha 6 (1.95329810 neste caso), então procurar seu valor mais próximo nas linhas seguintes, da primeira coluna (1.877 neste caso). Isso apenas para referenciar, depois de fundado isso, quero extrair a próxima linha cuja segunda coluna é diferente de zero (4.152).
Portanto, gostaria de obter 1,95329810 e 4,152 como saída, para poder subtraí-los e obter:
band_gap=4.152-$fermi_energy
Levando em consideração a resposta de @DopeGhoti, usei o código dele com uma instrução if:
#!/bin/bash
fermi_energy=$(awk 'NR==6 {printf $4}' DOSCAR-62.4902421.st)
awk -f go.awk DOSCAR-62.4902421.st
Onde go.awk
está o arquivo:
BEGIN {
test=0
}
NF == 3 && test == 0 && $2 != "0.0000E+00" {
keptvalue=$1
}
NF == 3 && test == 0 && $2 == "0.0000E+00" {
#print keptvalue
test=1
}
NF == 3 && test == 1 && $2 != "0.0000E+00" {
if ( sqrt(($fermi_energy-$1)**2) < 0.5 )
{
print $1
test=0
}
}
Mas acho que não é a maneira certa de usar variáveis bash dentro de um script awk.
PD Caso você esteja se perguntando , os dados representam os cálculos da densidade de estados dos elétrons de um óxido. A primeira coluna representa as energias do elétron, a segunda a quantidade do elétron naquele nível de energia. Portanto, ao procurar o próximo valor diferente de '0,0000E+00' desde o nível mais próximo da Energia de Fermi , podemos calcular a energia necessária para fazer os elétrons saltarem e conduzirem eletricidade. (Metais têm gap zero, portanto, não precisam de entrada de energia para conduzir eletricidade)
A resposta abaixo faz uma série de mudanças em sua técnica.
Faça tudo em um único
awk
programa em vez de dois. Você pode fazer isso porque sua segunda execução lida apenas com linhas após a linha 6:Atribua corretamente seu valor fermi_energy da linha 6.
Não é mais necessário verificar
NF==3
porque todas as linhas após a linha 6 atendem a esse critério.Elimine a variável
test
e, em vez disso, vamos manter uma guia contínua da diferença mínima entrefermi_energy
e$1
. Para isso, criaremos uma variávelmin
que inicialmente terá um valor ridiculamente grande, com garantia de falha no primeiro teste. Também atribuiremos nomes compreensíveis às outras variáveis e imprimiremos apenas um resultado, após testar todas as linhas do arquivo.Substitua seu teste de valor absoluto computacionalmente pesado por um teste de zero computacionalmente leve.
Observe que
awk
suporta notação científica de ponto flutuante. Por exemplo, em umprintf
comando, pode-se usar o formato%E
. Como de costume, consulte aman
página ou seu mecanismo de pesquisa favorito para saber mais.Tudo isso feito sem nenhum conhecimento de física de partículas, então posso ter entendido algo errado. Perdão. Se assim for, espero que pelo menos isso o coloque no caminho certo.
Para os dados de entrada fornecidos,
file
isso produziráO
awk
script ignora as primeiras cinco linhas de entrada. Na linha seis, ele escolhe o quarto campo e o atribui à variávelfe
(com exceção de "Fermi energy".O código então assume que os valores na coluna um estão aumentando, e quando o primeiro desses valores da primeira coluna atinge um valor acima do valor armazenado em
fe
, e se a segunda coluna for diferente de zero, ele imprimefe
e o valor da primeira coluna e sai.Infelizmente, não entendo totalmente seu segmento de código mais longo, pois não há explicação do que você realmente deseja que ele faça.