我有一个数据文件,其中包含一些示例数据(名字、姓氏、收入、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