Bucle de calculadora de script Bash

Bucle de calculadora de script Bash

Tengo un archivo de datos con algunos datos de muestra (nombre, apellido, ingresos, tasa Rax). Necesito hacer algunos cálculos, pero al mostrar el resultado, tengo problemas porque es un bucle y no se muestra en orden. Sí, debo usar bash.

Archivo de ejemplo:

------------------------------------
example-file.txt:

John,Rambo,99880,2%
Elon,Musk,144000,2%
------------------------------------

prueba.bash:

#/bin/bash

FILE=example-file.txt
 
for file in $FILE;
do
    # Get income
    INCOME=$(cat $file | awk -F, '{print $3}');
    FIRSTNAME=$(cat $file | awk -F, '{print $1}');
    LASTNAME=$(cat $file | awk -F, '{print $2}');
    # Get tax rate
    RATE=$(cat $file | awk -F, '{print $4}' | sed 's/%//');

    for foo in $INCOME
    do
     if [ "$foo" -ge 80000 ] && [ "$foo" -lt 150000 ];
        then
            for faa in $foo
            do
                NETINCOME=$(printf "%'.f\n" $(echo "(($INCOME * $RATE / 100))" | bc))
            done
    fi
    echo "${FIRSTNAME} ${LASTNAME} ${NETINCOME}"
   done
done

Producción:

(standard_in) 2: syntax error
(standard_in) 3: syntax error
John
Elon Rambo
Musk 288,000
(standard_in) 2: syntax error
(standard_in) 3: syntax error
John
Elon Rambo
Musk 288,000

Salida deseada:

John Rambo 1997
Elon Musk 2880

¿Cómo puedo lograr eso?

Respuesta1

Ya que estás utilizando awkpara extraer campos de tus líneas, ¿por qué no dejas que haga todo el trabajo? Debería tener suficientes capacidades aritméticas y convertir su script en un script AWK puede ser más fácil que arreglarlo.

$ cat example-file.txt 
John,Rambo,99880,2%
Elon,Musk,144000,2%
$ awk -v FS=, '{ print $1,$2,sprintf("%i", $3 * $4 / 100) }' example-file.txt 
John Rambo 1997
Elon Musk 2880

Utilice el primer argumento dado a sprintfpara ajustar el formato del número impreso.

También puedes filtrar líneas. Por ejemplo, suponiendo que solo le interesa un rango de ingresos:

$ awk -v FS=, '
  80000 < $3 && $3 < 150000 {
    print $1,$2,sprintf("%i",$3 * $4 / 100)
  }'

Acepta una cantidad arbitraria de archivos como argumentos (el límite superior depende de la configuración de su sistema; si tiene muchos, use find ... -exec awk ...):

awk -v FS=, '...' file1.txt file2.txt ...

Finalmente, puede guardar el script como un archivo, sin la 's adjunta, e invocarlo como:

awk -v FS=, -f awk_script file1.txt

eliminando la necesidad de concatenaciones de cadenas inconvenientes en caso de que necesite usar literales 'en alguna parte. Por ejemplo, si quisiera que la sprintfcadena de formato incluyera la 'bandera, el script en línea sería:

awk ... '... sprintf("%'"'"'.f", $3 * $4 / 100) ...' file

Respuesta2

Su guión tiene varios problemas. En primer lugar, está tratando las cadenas como matrices (no tiene sentido hacerlo for foo in $barcuando $bares solo una cadena). En segundo lugar, estás leyendo el archivo varias veces cuando todo lo que necesitas hacer es leerlo una vez. En tercer lugar, no está citando sus variables, lo que significa que el script se interrumpirá si los nombres de los archivos pueden contener espacios en blanco. Aquí hay una mejor manera:

#/bin/bash

## take a list of file names as an argument so you can
## work on multiple files.
for file in "$@";
do

  ## get the values
  while read firstName lastName income  rate; do
    rate=${rate//%}
    if [[ "$income" -ge 80000  && "$income" -lt 150000 ]]; then
      netIncome=$(printf "%'.f\n" $(echo "($income * $rate) / 100" | bc))
    ## You didn't specify what should happen if the income isn't in the
    ## target range, so I am assuming you want it to be the $income unchanged.
    else
      netIncome=$income
    fi
    echo "$firstName $lastName $netIncome"
  done < <(awk -F, '{print $1,$2,$3,$4}' "$file")
done

Puede ejecutar esto con los archivos como argumentos:

$ foo.sh file
John Rambo 1,997
Elon Musk 2,880

información relacionada