Eu tenho um arquivo parecido com este:
# Time-averaged data for fix avetimeall
# TimeStep Number-of-rows
# Row c_gyrationchunkall
1000 3
1 2.09024e-14
2 4.88628
3 5.69321
2000 3
1 2.10518e-14
2 8.33702
3 8.83162
3000 3
1 1.96656e-14
2 12.1396
3 11.5835
...
No meu arquivo, as três primeiras linhas são sempre cabeçalhos. Após os cabeçalhos, meu arquivo lista blocos de dados do mesmo tamanho, cada um começando com um subcabeçalho rotulado. Quero reorganizar os dados em meu arquivo de modo que os dados em cada bloco sejam enviados em uma linha começando com a parte relevante do rótulo desse bloco e listando posteriormente os valores de dados relevantes desse bloco, todos separados uns dos outros por espaços . Por exemplo, quero converter a amostra acima em:
# Time-averaged data for fix avetimeall
# TimeStep c_gyrationchunkall
1000 2.09024e-14 4.88628 5.69321
2000 2.10518e-14 8.33702 8.83162
3000 1.96656e-14 12.1396 11.5835
...
Como faço isso no Bash? Tenho alguma experiência em Bash, mas infelizmente não o suficiente para lidar com esse problema rapidamente...
Usando qualquer awk, independentemente de o
3
número de linhas em um bloco poder variar ou não:Seguindo uma discussão sob a resposta de Xavier G sobre uma preferência de estilo para legibilidade, aqui está um script awk escrito no mesmo estilo daquele script de shell (e contido em um script de shell para que se comporte da mesma maneira externamente), mas será executado ordens de magnitude mais rápidas* e mais robustas e portáveis que o shell script:
* Aqui estão os resultados do tempo da terceira execução da execução do script bash versus o script awk acima em um arquivo contendo 90.000 registros de OPs:
Usando Raku (anteriormente conhecido como Perl_6)
Use
skip
para esquecer as linhas de cabeçalho por enquanto:Acima está uma resposta codificada em Raku, um membro da família Perl de linguagens de programação. Resumidamente,
lines
são lidos eskip
executam ping nas três primeiras linhas do cabeçalho. Cada 4 linhas sãorotor
editadas/batch
editadas juntas, incluindopartial
"rotorings" finais no final do arquivo. Enquanto estamos nisso, vamos dividir cadarotor
/batch
em espaços em branco separadoswords
.Esses rotores/lotes de 4 linhas, cada um quebrado no espaço em branco, são salvos em uma
@
matriz -sigilada chamada@a
. Finalmente (na segunda instrução), o uso defor
cada@a
posição é iterado through e output
, tomando cuidado para que elementos indesejados sejam descartados (por meio de colchetes de indexação[0,3,5,7]
).Entrada de amostra:
Saída de amostra:
Em relação às linhas de cabeçalho, poderia ser igualmente fácil iniciar o código Raku com duas
put
instruções, por exemploput "Time-averaged data...";
, etc. Mas, de fato, o seguinte funciona para fornecer a saída desejada pelo OP:https://raku.org
Usando AWK :
Resposta rápida e suja - sinta-se à vontade para executar
shellcheck
isso:Uso:
./script_filename < input
Limitações:
Com as advertências mencionadas na sua pergunta e usando sua entrada de amostra como arquivo q762948, você pode fazer isso com um simples comando awk: