如何在 Bash 脚本中添加数字?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6348902/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 20:39:06  来源:igfitidea点击:

How can I add numbers in a Bash script?

bashinteger-arithmeticmathematical-expressions

提问by Nick

I have this Bash script and I had a problem in line 16. How can I take the previous result of line 15 and add it to the variable in line 16?

我有这个 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+=} END { print sum/120}') (line15)
        num= $num + $metab   (line16)
    done
    echo "$num"
 done

回答by Karoly Horvath

For integers:

对于整数

  • Use arithmetic expansion: $((EXPR))

    num=$((num1 + num2))
    num=$(($num1 + $num2))       # Also works
    num=$((num1 + 2 + 3))        # ...
    num=$[num1+num2]             # Old, deprecated arithmetic expression syntax
    
  • Using the external exprutility. Note that this is only needed for really old systems.

    num=`expr $num1 + $num2`     # Whitespace for expr is important
    
  • 使用算术扩展$((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
    


For floating point:

对于浮点

Bash doesn't directly support this, but there are a couple of external tools you can use:

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

You can also use scientific notation (for example, 2.5e+2).

您还可以使用科学记数法(例如,2.5e+2)。



Common pitfalls:

常见的陷阱

  • When setting a variable, you cannot have whitespace on either side of =, otherwise it will force the shell to interpret the first word as the name of the application to run (for example, num=or num)

    num= 1num =2

  • bcand exprexpect each number and operator as a separate argument, so whitespace is important. They cannot process arguments like 3++4.

    num=`expr $num1+ $num2`

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

    num= 1num =2

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

    num=`expr $num1+ $num2`

回答by Steve Prentice

Use the $(( ))arithmetic expansion.

使用$(( ))算术展开式。

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

See Chapter 13. Arithmetic Expansionfor more information.

有关详细信息,请参阅第 13 章算术扩展

回答by sorpigal

There are a thousand and one ways to do it. Here's one using dc(a reverse-polish desk calculator which supports unlimited precision arithmetic):

有一千零一种方法可以做到。这是一个使用dc(支持无限精度算术的反向抛光桌面计算器):

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

But if that's too bash-y for you (or portability matters) you could say

但是,如果这对您来说太过分了(或便携性很重要),您可以说

echo $num1 $num2 + p | dc

But maybe you're one of those people who thinks RPN is icky and weird; don't worry! bcis here for you:

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

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

That said, there are some unrelated improvements you could be making to your script:

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

#!/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+=} END { print sum/120}')
            num=$(( $num + $metab ))
    done
    echo "$num"
done

As described in Bash FAQ 022, Bash does not natively support floating point numbers. If you need to sum floating point numbers the use of an external tool (like bcor dc) is required.

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

In this case the solution would be

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

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

To add accumulate possibly-floating-point numbers into num.

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

回答by glenn Hymanman

In bash,

在 bash 中,

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

Note that bash can only handle integer arithmetic, so if your awk command returns a fraction, then you'll want to redesign: here's your code rewritten a bit to do all math in awk.

请注意,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 += }
               END {print n + (sum/120)}
           ' "$j"
        )
    done
    echo "$num"
done

回答by ssshake

I always forget the syntax so I come to google, but then I never find the one I'm familiar with :P. This is the cleanest to me and more true to what I'd expect in other languages.

我总是忘记语法,所以我来谷歌,但我从来没有找到我熟悉的:P。这对我来说是最干净的,并且更符合我对其他语言的期望。

i=0
((i++))

echo $i;

回答by Amarjeet Singh

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

回答by unixball

I really like this method as well, less clutter:

我也非常喜欢这种方法,减少杂乱:

count=$[count+1]

回答by Pavel

You should declare metab as integer and then use arithmetic evaluation

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

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

For more information see https://www.gnu.org/software/bash/manual/html_node/Shell-Arithmetic.html#Shell-Arithmetic

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

回答by Inian

Another portable POSIXcompliant way to do in bash, which can be defined as a function in .bashrcfor all the arithmetic operators of convenience.

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

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

and just call it in command-line as,

只需在命令行中调用它,

addNumbers 1 2 3 4 5 100
115

The idea is to use the Input-Field-Separator(IFS), a special variable in bashused for word splitting after expansion and to split lines into words. The function changes the value locally to use word-splitting character as the sum operator +.

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

Remember the IFSis changed locally and does NOTtake effect on the default IFSbehaviour outside the function scope. An excerpt from the man bashpage,

记住IFS局部改变,并没有采用默认效果IFS的功能范围之外的行为。从man bash页面摘录,

The shell treats each character of IFS as a delimiter, and splits the results of the other expansions into words on these characters. If IFS is unset, or its value is exactly , the default, then sequences of , , and at the beginning and end of the results of the previous expansions are ignored, and any sequence of IFS characters not at the beginning or end serves to delimit words.

Shell 将 IFS 的每个字符视为分隔符,并将其他扩展的结果拆分为这些字符上的单词。如果 IFS 未设置,或者它的值恰好是默认值,则忽略前面扩展结果的开头和结尾处的 、 和 序列,并且任何不在开头或结尾处的 IFS 字符序列用于分隔字。

The "$(( $* ))"represents the list of arguments passed to be split by +and later the sum value is output using the printffunction. The function can be extended to add scope for other arithmetic operations also.

"$(( $* ))"表示传递给被分割参数列表+和后来的总和值是使用输出printf功能。该函数还可以扩展为添加其他算术运算的范围。

回答by Milen John Thomas

#!/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+=} END { print sum/120}') (line15)
        let num=num+metab (line 16)
    done
    echo "$num"
done