Faz o loop através do diretório e soma o valor ao lado do padrão específico produzindo uma média

0

Eu quero percorrer todos os arquivos no diretório.

os arquivos são definidos assim:

<Overall>4
other data
<Overall>2
other data
......

Eu tenho o código:

for file in .dat; 
do
awk 'x+=sub(/<Overall>/,""){y+=$0} END{print FILENAME, y/x}' $file
done

isto imprime a média dos valores no arquivo, no entanto o que eu quero é pegar o diretório em que meu script está como argumento e fazer o comando awk em todos os arquivos .dat no diretório.

Eu tentei usar o código:

for file in $1

mas receba o erro:

awk: cmd. line:1: fatal cannot open file 'folder' for reading (No such file or directory)

Além disso, eu também quero poder classificar a saída dos valores médios de alto para baixo.

    
por tom 15.02.2016 / 21:21

1 resposta

0

Duas variações:

  1. Faça um loop sobre os arquivos e invoque awk uma vez para cada arquivo ou
  2. Dê ao script awk todos os arquivos e deixe-o calcular a média de cada um e o relatório conforme for avançando.

A classificação do resultado de qualquer uma das soluções abaixo pode ser feita pipetando sua saída por meio de

sort -k2,2rn

Isso faz uma classificação numérica inversa no segundo campo (as médias).

Primeira solução:

#!/bin/sh

for name in "$1"/*.dat; do
    test -f "$name" || continue   # skip non-files
    awk -F '>' '/<Overall>/ { s+=$NF; n++ } END { print FILENAME, s/n }' "$name"
done

Este script espera um nome de diretório na linha de comando como o primeiro e único argumento de linha de comando. O script awk encontrará todas as linhas que contêm a string Overall e resumirá (em s ) o valor após o > nessa linha. No final, a média é gerada junto com o nome do arquivo. A variável n contém o número de vezes que adicionamos algo a s .

Segunda solução (requer o GNU Awk):

#!/bin/sh

find "$1" -maxdepth 1 -type f -name '*.dat' \
    -exec awk -F '>' '/<Overall>/ { s+=$NF; n++ } ENDFILE { print FILENAME, s/n; s=n=0 }' {} +

Esse script, como o primeiro, espera um nome de diretório como seu único argumento de linha de comando. Ele usa find para executar um script awk com o máximo de .dat de arquivos possível no momento.

O script awk faz uso do gatilho ENDFILE do GNU Awk para gerar os valores calculados e redefinir as variáveis s e n depois de processar cada arquivo, antes de começar a ler o próximo arquivo.

Isso também pode ter sido escrito como

#!/bin/sh

awk -F '>' '/<Overall>/ { s+=$NF; n++ } ENDFILE { print FILENAME, s/n; s=n=0 }' "$1"/*.dat

mas isso depende de "$1"/*.dat não ser expandido para uma lista muito longa de nomes de arquivos (isso também requer que cada nome .dat seja um arquivo regular, que é algo que o comando find acima garante com -type f ) .

    
por 19.09.2017 / 22:21