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

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

我想知道

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

所有 4 个都将 2 赋值给变量 a,但是有什么区别呢?

从我目前发现的情况来看,expr 速度较慢是因为它不是真正的 shell 内置命令。但仅此而已。

答案1

所有这些都处理算术,但方式不同,变量的创建方式也不同。其中一些是bashshell 特有的,而另一些则不是。

  • $((...))叫做算术扩展,这是bashksh壳的典型特征。这允许执行简单的整数算术,但没有浮点数。表达式的结果替换表达式,就像echo $((1+1))变成echo 2
  • ((...))被称为算术评估and 可以用作if ((...)); thenorwhile ((...)) ; do语句的一部分。算术扩展$((..))替换操作的输出,并可用于分配变量,如 in,i=$((i+1))但不能用于条件语句。
  • $[...] 是已弃用的旧算术扩展语法。也可以看看。保留这个可能是为了让旧bash脚本不被破坏。这个在 中不起作用ksh93,所以我猜这个语法是 bash 特有的。笔记:空格在这里非常重要;不要$[1+1]与诸如 之类的东西混淆[ $a -eq $b ][带空格的称为test命令,您通常会在决策部分看到它。它在行为和目的上非常不同。
  • let是一个bashandksh关键字,允许使用简单的算术求值创建变量。如果您尝试在那里分配一个字符串,let a="hello world"则会收到语法错误。适用于bashand ksh93
  • $(...)是命令替换,即您直接获取命令的输出并将其赋值给变量。此处的命令是expr,它接受位置参数,例如expr arg1 arg2 arg3,因此空格很重要。它有点像一个用于整数运算的小型命令行计算器,加上一些真/假和正则表达式类型的东西。这是一个与 shell 无关的命令。

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

答案2

  • let命令执行算术运算评估并且是内置的shell。

    • 运行此命令,您将不会得到任何结果(仅计算结果):

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

    • 运行这个,你会得到一个错误(由于扩展):

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

    旧格式 $[expression] 已被弃用并将在即将推出的 bash 中删除。 Bash 手册页

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

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

答案3

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

$ print $((1.0/3)) 
0.333333333333333333

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

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

至少一个参数必须指定为浮点数,如上所述。如果两者都指定为整数,则只进行整数运算,例如:

$ print $((1/3))  
0

当您需要 shell 脚本中的浮点数学时这会很有用,因为您可以避免调用外部命令。

答案4

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

let x=1+2
echo x=$x

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

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

在所有情况下结果都是“x=3”。

相关内容