我正在尝试添加由空格分隔的单行整数并找到它们的绝对值。共有 5 个整数,其中一个为负数,其他为正数。我正在尝试找到一种方法使当前的负值变为正值,以便找到所有数字的绝对值。这是我到目前为止所拥有的。
read input
# 1, 5, -17, 32, 12
# expected absolute value: 67
absolute_value()
{
local absolute_value=0
for nums in $input;
do
((absolute_value += nums))
done
echo $absolute_value
}
absolute_value
我的答案是 33,预期答案是 67。它们当然是相加的,但由于其中一个输入数字可能是负数,所以它给我的是总和而不是绝对值。我很困惑,一直在四处寻找答案,但我就是想不出答案。 Bash 不是我最擅长的语言,所以我可能会忽略它。
答案1
嗯,怎么样绝对值定义?
if [ "$num" -lt 0 ]; then
num=$((-num))
fi
无论如何,这:
for nums in $input
依赖于分词并且有点丑陋。如果有人输入非数字或全局字符,您也会得到有趣的效果。由于您使用的是 Bash,因此您可以通过将值读取到带有read -a
.另外,我们还可以使用[[ var -lt 0 ]]
.
然而,仅仅这样做并不好,因为 Bash 中的算术扩展是危险的。通过数组索引和命令替换可以很容易地注入命令,shell 将执行它们。因此,我们确实需要首先检查接收到的值是否是数字。
#!/bin/bash
read -a nums
sum=0
for a in "${nums[@]}"; do
if [[ $a = *[^-0-9]* ]]; then
echo "invalid number: $a"
exit 1
fi
if [[ a -lt 0 ]]; then
sum=$((sum + -a))
else
sum=$((sum + a))
fi
done
echo "$sum"
请注意,Bash 会将以 和 开头的数字分别解释0
为0x
八进制和十六进制。
或者,您知道,只需使用真正的编程语言即可,这样您就不需要手动完成所有操作:
$ python3 -c 'print(sum(map(lambda x: abs(int(x)), str.split(input()))))'
1 5 -17 32 12
67
答案2
您可以使用参数替换来删除减号:
读取输入 # 1, 5, -17, 32, 12 # 期望绝对值:67 绝对值() { 局部绝对值=0 对于 $input 中的数字;做 ((绝对值 +=${nums#-})) 完毕 回显$绝对值 } 绝对值
为了避免使用 for 循环,您可以尝试这样做:
printf "%s\n" ${input/-/} | awk '{ sum += $1 } END { print sum }'
我会使用 while 循环和数组来控制用户可以执行多少输入,并不断询问输入是否错误:
declare -a arr
declare -a arr_abs
echo "Enter four numbers:"
while true; do
read num
[[ $num =~ ^[^-0-9]$ ]] && echo "Not a number..." && continue
# keep the original values for any other use
arr+=($num)
# create an array with absolute values
arr_abs+=(${num#-})
[[ ${#arr[@]} -eq 4 ]] && break
done
absolute_value() {
sum=$(printf "%s\n" ${arr_abs[@]} | awk '{ sum += $1 } END { print sum }')
echo "The absolute sum is $sum"
}
absolute_value