Bash 腳本計算器循環

Bash 腳本計算器循環

我有一個資料文件,其中包含一些範例資料(名字、姓氏、收入、Rax 率)。我需要做一些計算,但是在顯示結果時,我遇到了麻煩,因為它是一個循環並且沒有按順序顯示。是的,我必須使用 bash。

範例檔:

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

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

測試.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

輸出:

(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

如果您需要在某處使用文字,則無需進行不方便的字串連接'。例如,如果您希望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

相關內容