如何在bash脚本中添加数字

时间:2011-06-14 19:25:43

标签: bash mathematical-expressions

我有这个bash脚本,我在第16行遇到了问题。 如何获取第15行的先前结果并添加 它到第16行的变量?

#!/bin/bash

num=0
metab=0

for ((i=1; i<=2; i++)); do      
    for j in `ls output-$i-*`; do
        echo "$j"

        metab=$(cat $j|grep EndBuffer|awk '{sum+=$2} END { print sum/120}') (line15)
        num= $num + $metab   (line16)
    done
    echo "$num"
 done

11 个答案:

答案 0 :(得分:835)

对于整数

  • 使用arithmetic expansion$((EXPR))

    num=$((num1 + num2))
    num=$(($num1 + $num2))       # also works
    num=$((num1 + 2 + 3))        # ...
    num=$[num1+num2]             # old, deprecated arithmetic expression syntax
    
  • 使用外部expr实用程序。请注意,只有真正的旧系统才需要这样做。

    num=`expr $num1 + $num2`     # whitespace for expr is important
    

对于浮点

Bash不直接支持此功能,但您可以使用几种外部工具:

num=$(awk "BEGIN {print $num1+$num2; exit}")
num=$(python -c "print $num1+$num2")
num=$(perl -e "print $num1+$num2")
num=$(echo $num1 + $num2 | bc)   # whitespace for echo is important

您也可以使用科学记数法(例如:2.5e+2


常见陷阱

  • 设置变量时,=的任何一侧都不能有空格,否则会强制shell将第一个单词解释为要运行的应用程序的名称(例如:{{1 }或num=

    num num= 1

  • num =2bc期望每个数字和运算符作为单独的参数,因此空格很重要。他们无法处理expr 3+等参数。

    <击> +4

答案 1 :(得分:85)

使用$(( ))算术扩展。

num=$(( $num + $metab ))

有关详细信息,请参阅http://tldp.org/LDP/abs/html/arithexp.html

答案 2 :(得分:25)

有一千零一种方法可以做到这一点。这是一个使用dc

dc <<<"$num1 $num2 + p"

但是如果这对你来说太过苛刻(或者便携性很重要)你可以说

echo $num1 $num2 + p | dc

但也许你是那些认为RPN狡猾而怪异的人之一;别担心! bc在这里为您服务:

bc <<< "$num1 + $num2"
echo $num1 + $num2 | bc

也就是说,您可以对脚本进行一些无关的改进

#!/bin/bash

num=0
metab=0

for ((i=1; i<=2; i++)); do
    for j in output-$i-* ; do # for can glob directly, no need to ls
            echo "$j"

             # grep can read files, no need to use cat
            metab=$(grep EndBuffer "$j" | awk '{sum+=$2} END { print sum/120}')
            num=$(( $num + $metab ))
    done
    echo "$num"
done

编辑:

BASH FAQ 022中所述,bash本身不支持浮点数。如果需要对浮点数求和,则需要使用外部工具(如bcdc)。

在这种情况下,解决方案将是

num=$(dc <<<"$num $metab + p")

将累积的可能浮点数添加到num

答案 3 :(得分:21)

在bash中,

 num=5
 x=6
 (( num += x ))
 echo $num   # ==> 11

请注意,bash只能处理整数运算,所以如果你的awk命令返回一个分数,那么你需要重新设计:这里你的代码重写了一下,用awk做了所有的数学运算。

num=0
for ((i=1; i<=2; i++)); do      
    for j in output-$i-*; do
        echo "$j"
        num=$(
           awk -v n="$num" '
               /EndBuffer/ {sum += $2}
               END {print n + (sum/120)}
           ' "$j"
        )
    done
    echo "$num"
done

答案 4 :(得分:16)

我总是忘记语法,所以我来谷歌,但后来我找不到我熟悉的那个:P。这对我来说是最干净的,对我在其他语言中的期望更为真实。

i=0
((i++))

echo $i;

答案 5 :(得分:15)

我也很喜欢这种方法,不那么混乱:

count=$[count+1]

答案 6 :(得分:9)

 #!/bin/bash
read X
read Y
echo "$(($X+$Y))"

答案 7 :(得分:8)

您应该将metab声明为整数,然后使用算术评估

declare -i metab num
...
num+=metab
...

有关详细信息,请参阅https://www.gnu.org/software/bash/manual/html_node/Shell-Arithmetic.html#Shell-Arithmetic

答案 8 :(得分:6)

POSIX中另一种可移植的bash兼容方式,可以在.bashrc中为所有算术运算符定义为函数。

addNumbers () {
    local IFS='+'
    printf "%s\n" "$(( $* ))"
}

,只需在命令行中调用它,

addNumbers 1 2 3 4 5 100
115

这个想法是使用Input-Field-Separator(IFS)bash中的一个特殊变量,用于扩展后的单词拆分,并将行拆分为单词。该函数在本地更改值以使用分词字符作为和运算符+

请记住IFS在本地更改,并且 NOT 对函数范围之外的默认IFS行为生效。摘自man bash页面,

  

shell将IFS的每个字符视为分隔符,并将其他扩展的结果拆分为这些字符上的单词。如果未设置IFS,或者其值正好是默认值,则会忽略先前扩展结果的开始和结束的,以及序列,并且不在开头或结尾的任何IFS字符序列用于分隔话。

"$(( $* ))"表示传递给+的参数列表,稍后使用printf函数输出和值。该函数可以扩展为其他算术运算添加范围。

答案 9 :(得分:2)

使用内置的let外壳程序,它类似于(( expr ))

A=1
B=1
let "C = $A + $B"
echo $C # C == 2

来源:https://www.computerhope.com/unix/bash/let.htm

答案 10 :(得分:1)

#!/bin/bash

num=0
metab=0

for ((i=1; i<=2; i++)); do      
    for j in `ls output-$i-*`; do
        echo "$j"

        metab=$(cat $j|grep EndBuffer|awk '{sum+=$2} END { print sum/120}') (line15)
        let num=num+metab (line 16)
    done
    echo "$num"
done