首页 文章

如何在bash脚本中添加数字

提问于
浏览
437

我有这个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

10 回答

  • 25

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

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

    但是,如果这对你来说太过苛刻(或者可移植性问题)你可以说

    echo $num1 $num2 + p | dc
    

    但也许你不用担心! 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 中 .

  • 1

    我也非常喜欢这种方法,不那么杂乱:

    count=$[count+1]
    
  • 14
    #!/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
    
  • 84

    在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
    
  • 16

    对于整数:

    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将第一个单词解释为要运行的应用程序的名称(例如: num=num

    num = 1 num = 2

    • bcexpr 期望每个数字和运算符作为单独的参数,因此空格很重要 . 他们无法处理像 3+ +4 这样的参数 .

    num =expr $ num1 $ num2

  • 5

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

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

    有关更多信息,请参见http://tldp.org/LDP/abs/html/arithexp.html .

  • 3

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

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

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

  • 5

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

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

    并在命令行中调用它,因为,

    addNumbers 1 2 3 4 5 100
    115
    

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

    请记住 IFS 在本地更改,并且不会对函数作用域外的默认 IFS 行为生效 . 摘自 man bash 页面,

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

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

  • 768

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

    i=0
    ((i++))
    
    echo $i;
    
  • 21
    #!/bin/bash
    read X
    read Y
    echo "$(($X+$Y))"
    

相关问题