Bash 中的算术表达式?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2517727/
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 19:06:12  来源:igfitidea点击:

Arithmetic expressions in Bash?

bashfloating-pointmathexpression

提问by Arko

I had used several ways to do some simple integer arithmetic in BASH (3.2). But I can't figure out the best (preferred) way to do it.

我曾使用多种方法在 BASH (3.2) 中进行一些简单的整数运算。但我想不出最好的(首选)方法来做到这一点。

result=`expr 1 + 2`
result=$(( 1 + 2 ))
let "result = 1 + 2"

What are the fundamental differences between those expressions?
Is there other ways to do the same?

这些表达之间的根本区别是什么?
还有其他方法可以做同样的事情吗?

Is the use of a tool like bcmandatory for floating point arithmetic?

是否bc必须使用浮点运算之类的工具?

result=`echo "7/354" | bc`

采纳答案by Paused until further notice.

In Bash, letallows multiple assignments on a line:

在 Bash 中,let允许在一行上进行多个赋值:

let a=3 b=4 c=5

As you show in your question, quoting the argument to letallows you to put spaces around the operators. You can, however, omit the quotes if you avoid using spaces.

正如您在问题中所示,引用参数 tolet允许您在运算符周围放置空格。但是,如果避免使用空格,则可以省略引号。

Another form using double parentheses at the beginning of the statement (instead of the i=$((j + 1))form) allows you to include spaces around the equal sign or do post- or pre- increment or decrement and additional assignment operations:

在语句开头使用双括号的另一种形式(而不是该i=$((j + 1))形式)允许您在等号周围包含空格或进行后或前自增或自减以及附加赋值操作:

(( a = ( b + c ) * 4 ))
(( count++ ))
(( d = --c**2 ))
(( e *= 2 ))
(( f = 3, g = 5 ))    # multiple operations require a comma separator

If you do help "(("it says that the double parentheses is 'Equivalent to "let EXPRESSION".'

如果你这样做,help "(("它会说双括号是“等效于“ let EXPRESSION”。

You can use the declarebuiltin to make assignments, including indirectly:

您可以使用declare内置函数进行赋值,包括间接赋值:

blue=2
name=blue
declare $name=4
echo $blue    # result: 4
echo ${!name} # result: 4

Edit:

编辑:

The $(())construct is called "arithmetic expansion" and causes the contents to be evaluated as an integer expression. It's a syntax element of the shell.

$(())构造称为“算术扩展”,并使内容被评估为整数表达式。它是 shell 的语法元素。

If a variable is declared as an integer you don't need to use either form of double parentheses, you can omit the dollar sign from the variable name (as in the double-parentheses forms), but you can't add spaces around operators:

如果变量被声明为整数,则不需要使用任何一种形式的双括号,可以省略变量名称中的美元符号(如双括号形式),但不能在运算符周围添加空格:

declare -i x=1   # set integer, initialize to 1
declare +i s=1   # clear integer, initialize to 1
x+=1             # could also be x=x+1
echo $x          # result: 2 (addition)
s+=1             # could also be s=$s+1, requires a "$"
echo $s          # result: 11 (string concatenation)

Unlike the forms above, calling exprinvolves spawning an external executable which can be quite expensive for a lot of calculations in a loop. The onlytime it should be used is in environments where the shell can't do its own arithmetic or for portability when a script may find its way into such an environment. POSIX shells have arithmetic capability so it would be a concern only with older systems.

与上面的形式不同,调用expr涉及生成一个外部可执行文件,这对于循环中的大量计算来说可能非常昂贵。它应该使用的唯一时间是在 shell 无法进行自己的算术运算或脚本可能会进入这样的环境时的可移植性的环境中。POSIX shell 具有算术能力,因此只有较旧的系统才会考虑它。

Regarding the use of bcfor floating point arithmetic, it or something similar is required when using Bash and many other shells. POSIX says that "Only signed long integer arithmetic is required."

关于bc浮点运算的使用,在使用 Bash 和许多其他 shell 时需要它或类似的东西。POSIX 说“只需要有符号长整数算术”。

Two shells that do support float math are ksh and zsh. In addition to bc, you can use dc, AWK, Python, Perl and others from within a Bash script.

支持浮点数学的两个 shell 是 ksh 和 zsh。除了 之外bc,您还可以dc在 Bash 脚本中使用、AWK、Python、Perl 等。

One thing that Bash willdo with floating point numbers is print them with the printfbuiltin (note that there is also an external printf, but builtins have priority).

Bash会对浮点数做的一件事是使用printf内置函数打印它们(请注意,还有一个 external printf,但内置函数具有优先权)。

printf "%'14.4f\n" 1234.56  # result "    1,234.5600" (in my locale)

回答by Carl Norum

I prefer your second option, since it doesn't need an external utility:

我更喜欢你的第二个选项,因为它不需要外部实用程序:

result=$(( 1 + 2 ))

The first option calls out to exprto do the math - I'm not familiar with let. Another alternative to bcis dc. Choose your favourite.

第一个选项要求进行expr数学计算 - 我不熟悉let. 的另一种替代方法bcdc。选择你最喜欢的。

回答by DVK

I can't say it's "mandatory" but bcis probably your best bet for general purpose arithmetic.

我不能说它是“强制性的”,但bc可能是通用算术的最佳选择。

For something fancier, you can always pipe through Perl.

对于更高级的东西,您总是可以通过 Perl 进行管道传输。

The downside of both thee approaches is that they both open a child process, so doing it in a tight loop will be slower than native bash expressions (same problem arises with use of backticks, in your first example). I'm not sure whether $(())calls a child process.

这两种方法的缺点是它们都打开了一个子进程,因此在紧密循环中执行它会比本地 bash 表达式慢(在您的第一个示例中,使用反引号会出现同样的问题)。我不确定是否$(())调用子进程。

回答by ghostdog74

Is the use of a tool like bc mandatory for floating point arithmetic?

Is the use of a tool like bc mandatory for floating point arithmetic?

No, if you are using a shell that supports floating point, eg zsh, ksh. Otherwise, if you want to do more advanced floating point maths, use either one of these, bc/awk/dc. Of course, Perl/Python etc as well.

不,如果您使用支持浮点的外壳,例如 zsh、ksh。否则,如果您想进行更高级的浮点数学运算,请使用其中之一,bc/awk/dc. 当然,还有 Perl/Python 等。

回答by Aye

The third option you have is a lot less readable as it does not look like an assignment operator. The first, as noted by others, calls an external command

您拥有的第三个选项的可读性要差得多,因为它看起来不像赋值运算符。第一个,正如其他人所指出的,调用外部命令