Цикл калькулятора скрипта Bash

Цикл калькулятора скрипта Bash

У меня есть файл данных с некоторыми образцами данных (Имя, Фамилия, Доход, Ставка Rax). Мне нужно сделать некоторые вычисления, но при отображении результата у меня возникают проблемы, так как это цикл, и он отображается не по порядку. Да, мне нужно использовать bash.

Пример файла:

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

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

тест.баш:

#/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

Выход:

(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

Желаемый результат:

John Rambo 1997
Elon Musk 2880

Как мне этого добиться?

решение1

Поскольку вы используете awkдля извлечения полей из ваших строк, почему бы вам просто не позволить ему сделать всю работу? Он должен иметь достаточные арифметические возможности, и преобразование вашего скрипта в скрипт AWK может быть проще, чем его исправление.

$ 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

Используйте первый аргумент, указанный sprintfдля настройки формата печатаемого числа.

Вы также можете фильтровать строки. Например, предположим, что вас интересует только диапазон доходов:

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

Он принимает произвольное количество файлов в качестве аргументов (верхняя граница зависит от конфигурации вашей системы; если у вас их много, используйте find ... -exec awk ...):

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

Наконец, вы можете сохранить скрипт как файл без закрывающих 'его s и вызвать его как:

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

устраняя необходимость в неудобной конкатенации строк в случае, если вам нужно 'где-то использовать литерал s. Например, если вы хотите, sprintfчтобы строка формата включала 'флаг, встроенный скрипт будет выглядеть так:

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

решение2

У вашего скрипта есть несколько проблем. Во-первых, вы обрабатываете строки как массивы (нет смысла или причины делать это, for foo in $barкогда $barэто всего лишь одна строка). Во-вторых, вы читаете файл несколько раз, когда все, что вам нужно сделать, это прочитать его один раз. В-третьих, вы не заключаете переменные в кавычки, что означает, что скрипт сломается, если имена файлов могут содержать пробелы. Вот лучший способ:

#/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

Вы можете запустить это с файлами в качестве аргументов:

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

Связанный контент