根据每月预测计算某一天的余额
calculate balance on certain day from monthly projection
我有一份我每月支出的清单,看起来像这样:
第 1 - 汽车 - 100
第 3 - 租金 - 400
第 7 - 天然气和电力 - 51
第 8 - Phone - 12
第 17 - 互联网 - 30.74
第 21 - 保险 - 45.21
第 27 - Patreon - 2
第 28 - 水 - 12.9
以上是一个示例,但在结构上与我的每月支出类似。
假设我在每个月的 23 号收到工资。我可以编写一个脚本(最好在 bash 中),我可以在其中输入我当前的银行余额,它会减去 $CURRENT_DATE 和每月 22 日之间从我的银行中流出的所有金额吗?
所以我可以 运行 这个月的任何时候这个脚本,并快速浏览一下我有多少剩余资金。
#!/bin/bash
PAYDAY=
B=
sed '/^$/d; s#\([0-9][0-9]*\)st##g; s#\([0-9][0-9]*\)nd##g; s#\([0-9][0-9]*\)th##g; s#\([0-9][0-9]*\)rd##g' | while read line
do
lday=$(echo $line | awk -F'-' '{print }')
amount=$(echo $line | awk -F'-' '{print }')
if [[ $lday -gt `date '+%d'` && $lday -lt $PAYDAY ]]; then
B=`echo "$B - $amount" | bc`
echo $B
fi
done | tail -1
如果余额为1000
cat list.txt | ./calc.sh 1000 23
这是一个带注释的 bash 解决方案,可能不是最佳解决方案:
#! /bin/bash
if [[ -z ]]; then
echo "Missing argument: current balance"
exit 2
fi
# current balance comes in as the first argument, multiplied by 100 for the cent-value (bc for decimal)
current_balance=$(scale=0; echo " * 100" | bc -l)
# current day without leading zero
current_day=$(date +"%-d")
# the last day of the current month
last_day_of_month=$(date -d "-$(date +%d) days +1 month" +"%d")
# the default target date is the 22.
target_day=22
offset=0
# if we're past the cut-off point, then we'll check until the 22. of next month
if (( ${current_day} > 22 )); then
target_day=$(( ${last_day_of_month} + 22 ))
offset=$(( $last_day_of_month ))
fi
# set the outgoings to be on the index of their date as their cent-values
outgoings=()
outgoings[1]=10000
outgoings[3]=40000
outgoings[7]=5100
outgoings[8]=1200
outgoings[17]=3074
outgoings[21]=4521
outgoings[27]=200
outgoings[28]=1290
# iterate over the days until we hit the target
for (( i=${current_day}; i < ${target_day}; i += 1 )); do
# decrement by the offset (either by 0 or the amount of days in month)
if (( $i > ${offset} )); then
index=$(( $i - $offset ))
else
index=$(( $i ))
fi
# if no outgoings for this day, continue
if [[ -z "${outgoings[index]}" ]]; then continue; fi
# calculate the current balance after this days outgoings
current_balance=$(( $current_balance - ${outgoings[index]} ))
done
# divide the current left over balance by 100 to get the euro/dollar/whatever amount
left_over=$(echo "scale=2; ${current_balance} / 100" | bc -l)
echo "Extra money: ${left_over}"
完整的 awk 解决方案是:
awk -v sal="1000" -v datnow=$(date +%d) -v dat=23 -F\- '{ dat=dat--;if ( [=10=] != "" && + >= datnow && +$i <= dat ) { vals[+]=+ } } END { for ( i in vals ) { sal=sal-vals[i] } print sal }' balances
其中 balances 是包含数据的文件。
我们将薪水作为 sal(示例 1000)传递,然后将发薪日作为 dat 传递。我们还将当前日期作为 datnow 传递。
我们将工资日减一 检查该行是否为空,检查文件中的日期是否大于或等于现在且小于或等于发薪日。如果是这种情况,则会创建一个数组,并最终通过从工资中减去值来获得剩余余额来循环此数组。
我有一份我每月支出的清单,看起来像这样:
第 1 - 汽车 - 100
第 3 - 租金 - 400
第 7 - 天然气和电力 - 51
第 8 - Phone - 12
第 17 - 互联网 - 30.74
第 21 - 保险 - 45.21
第 27 - Patreon - 2
第 28 - 水 - 12.9
以上是一个示例,但在结构上与我的每月支出类似。
假设我在每个月的 23 号收到工资。我可以编写一个脚本(最好在 bash 中),我可以在其中输入我当前的银行余额,它会减去 $CURRENT_DATE 和每月 22 日之间从我的银行中流出的所有金额吗?
所以我可以 运行 这个月的任何时候这个脚本,并快速浏览一下我有多少剩余资金。
#!/bin/bash
PAYDAY=
B=
sed '/^$/d; s#\([0-9][0-9]*\)st##g; s#\([0-9][0-9]*\)nd##g; s#\([0-9][0-9]*\)th##g; s#\([0-9][0-9]*\)rd##g' | while read line
do
lday=$(echo $line | awk -F'-' '{print }')
amount=$(echo $line | awk -F'-' '{print }')
if [[ $lday -gt `date '+%d'` && $lday -lt $PAYDAY ]]; then
B=`echo "$B - $amount" | bc`
echo $B
fi
done | tail -1
如果余额为1000
cat list.txt | ./calc.sh 1000 23
这是一个带注释的 bash 解决方案,可能不是最佳解决方案:
#! /bin/bash
if [[ -z ]]; then
echo "Missing argument: current balance"
exit 2
fi
# current balance comes in as the first argument, multiplied by 100 for the cent-value (bc for decimal)
current_balance=$(scale=0; echo " * 100" | bc -l)
# current day without leading zero
current_day=$(date +"%-d")
# the last day of the current month
last_day_of_month=$(date -d "-$(date +%d) days +1 month" +"%d")
# the default target date is the 22.
target_day=22
offset=0
# if we're past the cut-off point, then we'll check until the 22. of next month
if (( ${current_day} > 22 )); then
target_day=$(( ${last_day_of_month} + 22 ))
offset=$(( $last_day_of_month ))
fi
# set the outgoings to be on the index of their date as their cent-values
outgoings=()
outgoings[1]=10000
outgoings[3]=40000
outgoings[7]=5100
outgoings[8]=1200
outgoings[17]=3074
outgoings[21]=4521
outgoings[27]=200
outgoings[28]=1290
# iterate over the days until we hit the target
for (( i=${current_day}; i < ${target_day}; i += 1 )); do
# decrement by the offset (either by 0 or the amount of days in month)
if (( $i > ${offset} )); then
index=$(( $i - $offset ))
else
index=$(( $i ))
fi
# if no outgoings for this day, continue
if [[ -z "${outgoings[index]}" ]]; then continue; fi
# calculate the current balance after this days outgoings
current_balance=$(( $current_balance - ${outgoings[index]} ))
done
# divide the current left over balance by 100 to get the euro/dollar/whatever amount
left_over=$(echo "scale=2; ${current_balance} / 100" | bc -l)
echo "Extra money: ${left_over}"
完整的 awk 解决方案是:
awk -v sal="1000" -v datnow=$(date +%d) -v dat=23 -F\- '{ dat=dat--;if ( [=10=] != "" && + >= datnow && +$i <= dat ) { vals[+]=+ } } END { for ( i in vals ) { sal=sal-vals[i] } print sal }' balances
其中 balances 是包含数据的文件。
我们将薪水作为 sal(示例 1000)传递,然后将发薪日作为 dat 传递。我们还将当前日期作为 datnow 传递。
我们将工资日减一 检查该行是否为空,检查文件中的日期是否大于或等于现在且小于或等于发薪日。如果是这种情况,则会创建一个数组,并最终通过从工资中减去值来获得剩余余额来循环此数组。