let,expr和$ []之间的区别


23

我想知道两者之间到底有什么区别

a=$[1+1]
a=$((1+1))
let a=1+1
a=$(expr 1 + 1 )

所有4给变量a分配2,但是有什么区别?

到目前为止,我发现expr较慢,因为它不是实际的内置shell。但仅此而已。

Answers:


25

所有这些都处理算术,但是方式不同,并且变量是通过不同的方式创建的。其中一些特定于bash外壳,而另一些则不是。

  • $((...))称为算术扩展,这是bashand ksh外壳的典型特征。这允许执行简单的整数运算,但是没有浮点数。表达式的结果将替换表达式,如echo $((1+1))将成为echo 2
  • ((...))被称为算术评估,可以用作if ((...)); thenwhile ((...)) ; do语句的一部分。算术扩展扩展可$((..))替代操作的输出,可用于分配变量,i=$((i+1))但不能在条件语句中使用。
  • $[...] 是不推荐使用的旧算法扩展语法。另请参阅。这可能会保留下来,以便旧bash脚本不会中断。这在中不起作用ksh93,所以我的猜测是该语法是bash特定的。注意:这里的空格非常重要;不要混淆$[1+1]诸如此类的东西[ $a -eq $b ]。在[与空间是被称为test命令,你通常会看到它在决策部分。在行为和目的上有很大的不同。
  • letbashand ksh关键字,它允许通过简单的算术评估创建变量。如果您尝试在其中分配字符串,则可能let a="hello world"会遇到语法错误。在bash和中工作ksh93
  • $(...)是命令替换,在这里您可以从字面上获取命令的输出并分配给变量。您的命令是expr,它接受位置参数,例如expr arg1 arg2 arg3,因此空格很重要。它有点像一个用于整数运算的小型命令行计算器,外加一些true / false和regex类型的东西。这是一个与外壳无关的命令。

还值得注意的是,算术扩展和命令替换是由POSIX标准指定的,而let$[...]不是。


1
((...))实际上,可用于在分配bashkshzshn=10; ((n+=10)); echo $n打印20和((x=1)); echo $x打印1.
Alexej马古拉

1
@Alexej谢谢。答案已更新,该部分已删除
Sergiy Kolodyazhnyy

11
  • let该命令执行算术求值并且是内置的Shell。

    • 运行以下命令,您一无所获(仅求值):

      let 1+2
  • $(( ))用于执行算术扩展在此处阅读

    • 运行此命令,您将得到一个错误(由于扩展):

      $((1+2))
  • $[ ] 是算术扩展的旧语法:

    旧格式$ [expression]已弃用,在bash即将发布时将被删除。 重击手册页

  • expr 是二进制命令,如果要在命令替换中进行算术扩展,可以使用它:

    echo $(expr 1 + 2) 
    echo `expr 1 + 2`

4

由于上面的一些答案特别提到,ksh93因此值得注意的是,它可以进行浮点运算,例如:

$ print $((1.0/3)) 
0.333333333333333333

您可以使用printf控制输出的精度,例如:

$ printf "%.4f\n" $((1.0/3))
0.3333

如上所述,必须至少指定一个参数作为浮点数。如果两个都指定为整数,则仅完成整数数学运算,例如:

$ print $((1/3))  
0

当您需要在Shell脚本中进行浮点运算时,这将很有帮助,因为可以避免调用外部命令。


在我看来,您可能有兴趣发布以下答案:是否可以在bash脚本中使用分数/小数?尽管有标题,但我认为上下文清楚地表明其他Bourne风格的贝壳都相关,这就是为什么我发布zsh答案。因为kshbash彼此之间(通常)比彼此更相似zsh,所以在我看来,kh93基于该问题的答案可能非常有用。
伊莱亚·卡根

1

let在cron中不起作用。我认为这是由于let拥有自己的环境。$((...))因为它是POSIX,所以使用。例如,

let x=1+2
echo x=$x

在cron中,从shell运行时结果为“ x =”,但结果为“ x = 3”。

x=$((1+2))
echo x=$x

在所有情况下均导致“ x = 3”。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.