在Linux系统的Shell脚本编写过程中,条件判断是基础且关键的一环。很多初学者在比较数值时都会碰到eq这个写法,但并不清楚它到底代表什么、该用在什么地方。简单来说,eq是Bash等POSIX风格Shell中用于整数相等比较的测试操作符,全称为equal,只能在条件测试结构里发挥作用,用来判断左右两边的整数值是否相等。它不属于数学运算符,也不是通用等号,理解这一点是写好脚本的前提。

eq的底层原理与适用结构
从底层实现来看,eq是Shell内置命令test(也叫[)以及关键字[[所支持的二元整数比较算子。当Shell解析到[ 1 -eq 1 ]这样的语句时,并不会做字符串匹配,而是调用内部的整数解析逻辑,将两侧参数转换为长整型后再比较数值。这意味着如果传入的不是纯整数,例如[ "01" -eq 1 ],Shell仍会把它规范化成整数1后判定相等,而字符串比较则不会这样处理。
在Bash中,eq必须配合-eq这种带短横线的形式出现,单独写eq会被当作普通字符串或命令名。它主要出现在三种结构里:首先是传统的test命令或中括号[ ],例如if [ $a -eq $b ];其次是双方括号[[ ]],写法同样是[[ $a -eq $b ]];再次是case语句之外的算术复合命令中不能直接用,但在(( ))算术求值里则要用==或=而非eq。这种区分常常让新手混淆。
为了直观看到不同结构的差异,可以参考下面这段示例,它演示了正确使用-eq的方式以及错误用法带来的问题:
#!/bin/bash a=10 b=10 # 正确:在 [ ] 中使用 -eq 做整数比较 if [ $a -eq $b ]; then echo "a 等于 b" fi # 正确:在 [[ ]] 中使用 -eq if [[ $a -eq $b ]]; then echo "使用 [[ ]] 同样成立" fi # 错误示范:在 (( )) 里写 -eq 会语法报错 # if (( a -eq b )); then # echo "错误写法" # fi
eq与字符串比较及算术运算符的区别
不少脚本bug源于把eq和字符串比较符=、==混用。在[ ]中,=用于判断左右字符串是否完全一致,而-eq只看数值。例如变量x=" 2"(带空格)和y=2,用[ "$x" = "$y" ]会返回假,因为字符串不同;但用[ "$x" -eq "$y" ]时,Shell会忽略空格并转整数比较,返回真。这种隐性转换在调试时容易让人困惑,因此建议变量赋值时保持干净,比较时明确用途。
另一个常见误区是在算术表达式(( ))里使用eq。Bash的算术上下文遵循C语言风格,相等判断要用==或=,写成(( a == b ))。如果强行写(( a -eq b )),Bash会把-eq解析成减法与变量名,导致逻辑完全错误甚至报错。下面的代码展示了两者对比:
#!/bin/bash x=5 y=5 # 算术上下文中用 == if (( x == y )); then echo "算术比较成立" fi # 字符串上下文用 = if [ "$x" = "$y" ]; then echo "字符串相等" fi # 整数测试用 -eq if [ "$x" -eq "$y" ]; then echo "整数相等" fi
从可移植性角度讲,-eq是IEEE Std 1003.1(POSIX)规定的标准测试算子,几乎所有Unix Like系统的/bin/sh都支持;而[[ ]]和(( ))属于Bash扩展,在纯净sh环境可能不可用。因此如果脚本开头是#!/bin/sh,应坚持用[ ]加-eq的写法,避免兼容问题。
使用eq时的排错与最佳实践
当脚本因为eq相关逻辑出现异常时,优先检查变量是否真的为整数。若变量可能为空或含非数字字符,[ $var -eq 0 ]会直接报integer expression expected错误。稳妥的做法是先做合法性校验,或用默认值代入,例如num=${var:-0}再比较。对于用户输入,建议用正则或case语句过滤,防止恶意空值让条件测试崩溃。
在复杂脚本里,推荐把数值比较统一封装成函数,减少重复写-eq导致的笔误。同时,开启set -u和set -e能帮助及早发现未定义变量和判断失败。如下示例展示了一个安全的比较函数:
#!/bin/bash
set -u
safe_eq() {
local a="${1:-0}"
local b="${2:-0}"
# 简单整数校验
case "$a" in
''|*[!0-9-]*) a=0 ;;
esac
case "$b" in
''|*[!0-9-]*) b=0 ;;
esac
[ "$a" -eq "$b" ]
}
if safe_eq "$1" 100; then
echo "传入参数等于100"
else
echo "不等于100或非法"
fi
最后要提醒的是,不要为了省事在字符串和数值混用的场景只依赖-eq。明确数据的语义类型,该用字符串比较就用=,该用算术就用(( )),才能让Linux下的Shell脚本既健壮又易读。理清eq的真实含义,是迈向专业运维开发的一小步,却能有效减少线上事故。