Como você obtém um decimal de uma operação matemática envolvendo uma variável?

1

Estou tentando encontrar derivar SCALEFACTOR , que é basicamente 10000/(sum of 4th column in a file) . Como obtenho um decimal da saída? Agradecemos qualquer ajuda antecipadamente.

#!/bin/bash

FILES=/path/to/files/*;
for f in ${FILES}
do
    echo $f
    COLTOTAL="$(awk '{sum += $4} END {print sum}' $f)"
    echo "total: ${COLTOTAL}"
#    SCALEFACTOR='expr 10^5 / $COLTOTAL'
    B=10000
    SCALEFACTOR=$((B / ${COLTOTAL}))
    SCALINGFACTOR=$(echo "100000 / $COLTOTAL" | bc -l
#    echo "scale=5; ${SCALEFACTOR}" | bc
    echo ${SCALEFACTOR}
    awk '{print($1"\t"$2"\t"$3"\t"$4 * ${SCALINGFACTOR})}' $f > $f"_normalized.txt"

done
    
por Stephen 24.02.2015 / 19:48

1 resposta

0

A maneira como você implementou o loop for será interrompida se você tiver arquivos com espaços neles. Ele funcionará muito bem sem a variável for f in /path/to/files/* , já que a expansão acontece de maneira que o loop for possa entender.

Geralmente, como custa recursos para criar novos processos, é melhor ter apenas uma instância de awk e, como observou @ jw013, você deve executar a divisão fora do shell, pois sh e bash são incapazes de matemática de ponto flutuante.

Como você precisa do conhecimento do final do arquivo para manipular cada linha, você tem duas opções: ler cada arquivo, salvar cada linha para a segunda leitura ou ler cada arquivo duas vezes. Como salvar arquivos grandes na memória pode ser problemático, optei pela segunda opção:

for f in /path/to/files/*; do
  echo "$f"
  awk '
    NR == FNR {
      sum += $4;
      next;
    }
    FNR == 1 {
      print "total: " sum;
      SCALEFACTOR = 10000 / sum;
      print SCALEFACTOR;
    }
    {
      printf("%s\t%s\t%s\t%f\n", $1, $2, $3, $4 * SCALEFACTOR);
    }' "$f" "$f"

NR == FNR diz que o número do registro geral (linha) é o mesmo que o número do registro do arquivo atual, o que significa que você está no primeiro arquivo e a tarefa em questão é determinar a soma. next impede que as outras cláusulas sejam disparadas. Caso contrário, se na primeira linha da segunda leitura do arquivo, fizermos o que você tinha entre suas chamadas awk . Para cada linha na segunda leitura, imprimimos os quatro itens, com o quarto item dimensionado como você indicou.

Você pode usar a formatação de string padrão nesse quarto item, por exemplo, sua escala de cinco bc comentada alteraria meu %f para %.5f

    
por 07.03.2015 / 01:46