一、Shell 里有哪些常见运算符

原笔记列出的常见运算符包括:

  • +:加法
  • -:减法
  • *:乘法
  • /:除法
  • %:取余
  • ^**:幂运算
  • i++:计数
  • j+=n:累加
  • &&:前一个命令成功后再执行后一个命令
  • ||:前一个命令失败后再执行后一个命令

其中 % 在 Shell 自动化里还有一个非常高频的用途:生成范围随机数。

echo $((RANDOM % 5))

这会得到一个 04 之间的随机数。

二、用 &&|| 可以快速表达简单逻辑

原笔记举了两个很经典的场景:

ls /etc && echo 目录存在
ls /data || mkdir -p /data

这种写法虽然简洁,但只适合表达很短的逻辑。判断越来越复杂时,还是应该切换到 if

三、Shell 里常见的 5 种计算方式

原笔记把计算方法总结为:

  • awk
  • bc
  • expr
  • let
  • $(( ))$[]

3.1 awk:最灵活,支持小数

awk 很适合做带小数的计算,也是 Shell 与文本处理结合最紧密的方式。

awk 'BEGIN{print 1/3}'
awk -vn1=1 -vn2=3 'BEGIN{print n1/n2}'

-v 选项是重点,它相当于 Shell 和 awk 之间的桥梁。

3.2 bc:适合直接做浮点计算

echo 1/3 | bc -l

-l 的作用是让 bc 具备小数运算能力。

3.3 expr:老牌方案,整数计算居多

expr 有两个特别容易踩坑的点:

  • 运算符两边必须有空格
  • * 需要转义
expr 1 + 1
expr 1 \* 1
expr 1 / 1

尽管它现在不是最舒服的计算方式,但很适合配合返回值做“是不是数字”的快速检查。

3.4 let:最适合自增和整数运算

n1=666
n2=666
let c=n1+n2
let i++

以后写循环时,let i++ 会反复出现。

3.5 $(( ))$[]

这两种写法都能做整数计算:

n1=666
n2=666
echo $((n1+n2))
e=$[n1+n2]
echo $e

实际工作里更推荐 $(( )),可读性更好,也更主流。

四、实战:先用 expr 检查输入是否为数字

原笔记给出了一个很经典的技巧:

expr "$num1" + "$num2" + 666 &>/dev/null
if [ $? -ne 0 ]; then
    echo "Usage: $0 数字1 数字2"
    echo "请输入数字"
    exit 1
fi

这个技巧的核心是:如果 expr 计算失败,说明至少有一个输入不是有效数字。

五、案例一:命令行传参版计算器

下面这个脚本来自原笔记,逻辑很完整:先接参数,再检查,再计算,最后输出。

#!/bin/bash
num1=$1
num2=$2

expr "$num1" + "$num2" + 666 &>/dev/null
if [ $? -ne 0 ]; then
    echo "Usage: $0 数字1 数字2"
    echo "请输入数字"
    exit 1
fi

plus=$(awk -vn1=$num1 -vn2=$num2 'BEGIN{ print n1+n2 }')
min=$(awk -vn1=$num1 -vn2=$num2 'BEGIN{ print n1-n2 }')
cheng=$(awk -vn1=$num1 -vn2=$num2 'BEGIN{ print n1*n2 }')
chu=$(awk -vn1=$num1 -vn2=$num2 'BEGIN{ print n1/n2 }')

cat <<EOF
计算$num1 + $num2=$plus
计算$num1 - $num2=$min
计算$num1 * $num2=$cheng
计算$num1 / $num2=$chu
EOF

调用方式:

bash /server/scripts/devops-shell/11.calc_num.sh 1 2

这个版本很适合放在自动化流程里被其他脚本调用。

六、案例二:交互输入版计算器

如果希望用户运行脚本后再输入数字,可以改成 read 形式:

#!/bin/bash
read -p "请输入任意两个数字:" num1 num2

expr "$num1" + "$num2" + 666 &>/dev/null
if [ $? -ne 0 ]; then
    echo "Usage: $0 数字1 数字2"
    echo "请输入数字"
    exit 1
fi

plus=$(awk -vn1=$num1 -vn2=$num2 'BEGIN{ print n1+n2 }')
min=$(awk -vn1=$num1 -vn2=$num2 'BEGIN{ print n1-n2 }')
cheng=$(awk -vn1=$num1 -vn2=$num2 'BEGIN{ print n1*n2 }')
chu=$(awk -vn1=$num1 -vn2=$num2 'BEGIN{ print n1/n2 }')

cat <<EOF
计算$num1 + $num2=$plus
计算$num1 - $num2=$min
计算$num1 * $num2=$cheng
计算$num1 / $num2=$chu
EOF

这个版本更适合教学、交互工具和本地练习。

七、为什么计算器案例很重要

这个案例虽然简单,但它几乎把一个合格 Shell 脚本的基本结构都覆盖到了:

  • 参数获取
  • 输入检查
  • 使用命令做计算
  • 用变量保存结果
  • 统一输出

后面写更复杂的自动化脚本时,整体骨架其实还是这一套。

八、这一篇的推荐结论

如果只记一种实战方案,推荐组合是:

  • 输入检查:正则或 expr
  • 浮点计算:awkbc
  • 自增计数:let$(( ))

这样既兼顾可读性,也兼顾脚本里的通用性。真正进入循环、判断和函数之后,这些计算方式还会继续反复出现。