【问题标题】:Bash math expressionBash 数学表达式
【发布时间】:2020-10-03 13:04:28
【问题描述】:

我需要帮助来解决这个问题。

我读取了一个带有整数的变量10 20 -30

全部由空格分隔。我尝试将减号更改为加号并将其保存到另一个变量中,但它没有保存。如果我不能更改为 plus,我想将其删除,那么我可以这样做:

var=$((${num// /+/}))

所以它可以将所有整数相加。

这就是我所拥有的:

read num
echo $num
sum=$num | sed -e 's/-/+/g'
echo $sum

【问题讨论】:

  • re: '将减号改为加号并保存到另一个变量中': num='10 20 -30' ; num2="${num//-/+}" ; echo "${num2}" => 10 20 +30
  • re: '添加所有整数': echo "$(( ${num// /+} ))" => 0 ; echo "$(( ${num2// /+} ))" => 60

标签: bash math parameter-expansion


【解决方案1】:

使用标准 POSIX 变量扩展和算术:

#!/usr/bin/env sh

# Computes the sum of all arguments
sum () {
  # Save the IFS value
  _OIFS=$IFS

  # Set the IFS to + sign
  IFS=+

  # Expand the arguments with the IFS + sign
  # inside an arithmetic expression to get
  # the sum of all arguments.
  echo "$(($*))"

  # Restore the original IFS
  IFS=$_OIFS
}

num='10 20 -30'

# shellcheck disable=SC2086 # Intended word splitting of string into arguments
sum $num

具有join 功能的更多功能版本:

#!/usr/bin/env sh

# Join arguments with the provided delimiter character into a string
# $1: The delimiter character
# $@: The arguments to join
join () {
  # Save the IFS value
  _OIFS=$IFS

  # Set the IFS to the delimiter
  IFS=$1

  # Shift out the delimiter from the arguments
  shift

  # Output the joined string
  echo "$*"

  # Restore the original IFS
  IFS=$_OIFS
}

# Computes the sum of all arguments
sum () {
  # Join the arguments with a + sign to form a sum expression
  sum_expr=$(join + "$@")

  # Submit the sum expression to a shell's arithmetic expression
  # shellcheck disable=SC2004 # $sum_expr needs its $ to correctly split terms
  echo "$(($sum_expr))"
}

num='10 20 -30'

# shellcheck disable=SC2086 # Intended word splitting of string into arguments
sum $num

【讨论】:

  • 小心,玩IFS 可能会导致无人看管的行为!
  • 不错! +1 符合 POSIX 标准!下一步:创建一个函数以避免使用set --(即不要触摸脚本参数)。
  • @F.Hauri 使它成为一个函数
【解决方案2】:

简单地说:鞭打最后一个斜线:

num="10 20 -30"
echo $((${num// /+}))
0

一些细节

*Bash 连线替换 与所谓的正则表达式 没有任何共同之处。正确的语法是:

   ${parameter/pattern/string}

... 如果 pattern 以 / 开头,pattern 的所有匹配项都将替换为字符串。 通常只替换第一场比赛。 ...

见:man -Pless\ +/parameter.pattern.string bash

如果你尝试你的语法:

echo ${num// /+/}
10+/20+/-30

然后

echo ${num// /+}
10+20+-30

甚至,为了让它更漂亮:

echo ${num// / + }
10 + 20 + -30

但结果会保持不变:

echo $((  ${num// / + }  ))
0

【讨论】:

  • 如果有一个减号,双斜线也是多余的,如果不是完全错误的话。
  • @tripleee 10 + 20 + -30 是正确的! (空格是可选的)......即使10 - 20 - -30也是正确的!
  • @tripleee 也许你更喜欢:echo ${num// / + } -> 10 + 20 + -30 ?
【解决方案3】:
sum=$num | sed -e 's/-/+/g'

关于上面的内容,sum=$numsed 成为两个不同的命令。它没有按您的意愿组合在一起,这使得sed 无效。

另外,你需要echo $num

解决方案是将它们组合在一起,例如:

sum=`echo $num | sed -e 's/-/+/g`

sum=$(echo $num | sed -e 's/-/+/g')

或者,另一种方法

sum=${num//-/+}

【讨论】:

  • 避免无用的分叉:sed 's/X/Y/g' <<<"$varname"' instead of echo $varname | sed ...`!
最近更新 更多