侧边栏壁纸
博主头像
泡泡吐puber 博主等级

在这里,吐个有趣的泡泡🫧

  • 累计撰写 15 篇文章
  • 累计创建 8 个标签
  • 累计收到 25 条评论

目 录CONTENT

文章目录

Linux Shell 脚本学习记录:搞懂 $((...)) 和 ((...)) 的区别

泡泡吐puber
2025-10-07 / 0 评论 / 0 点赞 / 7 阅读 / 0 字 / 正在检测是否收录...

前言

今天在学习 Shell 脚本时,遇到了一个关于算术运算的问题,主要围绕 $((...))((...)) 这两种结构。在查阅资料和实践后,我将自己的理解整理为这篇笔记。

问题的产生

起初,我看到一段用于生成随机数的代码:

# 获取一个 0 到 2 之间的随机整数
num=$((RANDOM % 3))
echo "生成的随机数是: $num"

这让我有些疑惑。根据以往的经验,获取变量值应该使用 $VAR 的形式,比如 $RANDOM。但在这行代码里,$ 符号却被放在了整个括号表达式的外面。

紧接着,我又看到了在 if 语句中类似的用法,但这次 $ 符号完全消失了:

# 判断随机数是否为零
if ((RANDOM % 3)); then
    echo "结果不为零"
else
    echo "结果为零"
fi

这让我产生了几个疑问:

  1. $((...))((...)) 的具体功能和区别是什么?
  2. 为什么 $ 有时在外面,有时又完全不需要?
  3. 为什么在 ((...)) 结构里,RANDOM 变量不需要加 $ 符号?

$((...))((...)) 的功能辨析

经过研究,我发现它们虽然看起来相似,但用途完全不同。

1. $((...)):用于算术扩展和获取结果

$((...)) 的官方叫法是“算术扩展”(Arithmetic Expansion)。它的核心功能可以概括为两步:

  • 计算:执行双括号内部的数学表达式。
  • 扩展/替换:将计算出的最终结果替换到命令行的当前位置。

这里的 $ 符号是执行“扩展/替换”这一步的关键。它负责将计算结果“取”出来,并作为实际的值参与到后续的命令中。

例如,在 num=$((RANDOM % 3)) 中:

  1. ((RANDOM % 3)) 部分先进行计算,假设 RANDOM 是 12346,那么 12346 % 3 的结果是 1
  2. $ 将结果 1 取出,并替换掉 $((RANDOM % 3)) 这部分。
  3. 因此,原始命令最终等同于执行 num=1

所以,当我们需要的算术表达式的数值结果时,就应该使用 $((...))

2. ((...)):用于执行计算或条件判断

((...)) 是一个算术求值命令。它不会返回值,而是根据计算结果设置一个退出状态码(Exit Status),这使得它非常适合用在条件判断语句中。

它的工作逻辑是:

  • 如果表达式的计算结果不为 0,那么命令的退出状态码为 0(在 Shell 中代表 true)。
  • 如果表达式的计算结果为 0,那么命令的退出状态码为 1(在 Shell 中代表 false)。

这就是为什么 if ((RANDOM % 3)) 能够工作的原因。if 语句关心的不是具体的数值,而是其后的命令退出状态码是 0 (true) 还是 1 (false)。

此外,((...)) 也可以直接用来执行运算,尤其是改变变量值的操作,功能上类似于 let 命令。

i=10
((i = i + 1)) # 直接改变了变量 i 的值
((i++))       # 同样可以
echo $i      # 输出 12

关于在 ((...)) 中省略 $ 的说明

最后一个疑问是,为什么在 ((...)) 这个结构内,可以直接使用 RANDOM 而不是 $RANDOM

这是因为 ((...)) 提供了一个特殊的算术上下文。在这个上下文中,Shell 会自动将看起来像变量名的字符识别为变量,并获取它的值进行计算。这是一种为了让语法更接近 C 等编程语言而做的设计。

  • 常规上下文echo RANDOM 只会输出字符串 "RANDOM"。必须用 echo $RANDOM 才能让 Shell 先进行变量替换。
  • 算术上下文((num = RANDOM)) 中,Shell 知道 RANDOM 是一个变量,会自动获取其数值。

当然,在 ((...)) 内部使用 $RANDOM 也是可以的,Shell 会做兼容处理,但通常认为这是一种不必要的冗余写法。

总结

  • $((...))获取结果。它执行计算,然后将最终的数值返回(扩展)到命令中,用于赋值、输出等场景。
  • ((...))执行或判断。它执行计算,主要用于改变变量的值,或根据结果的真/假(非零/零)来设置退出状态码,多用于 ifwhilefor 循环。
  • 上下文差异:在 ((...)) 这个特殊的算术上下文中,可以直接通过名称使用变量,无需添加 $ 前缀。

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区