当字符串比较使用数字运算符时,Bash 中的分支经常执行错误的路径-eq或者当变量不加引号时。切换到 Bash[[ ]]使用正确的运算符进行测试可以修复这些逻辑错误并使脚本更易于维护。
方法一:用 Bash 编写 if...else[[ ]](字符串、数字和文件)
步骤一:创建一个新脚本并使用现代 Bash 测试语法添加最小条件[[ ]]。这种形式避免了意外的全局扩展和分词,与单括号相比,这减少了令人惊讶的行为。
#!/usr/bin/env bash
set -euo pipefail
read -r -p "Enter a value: " val
if [[ "$val" == "admin" ]]; then
echo "Welcome, admin."
else
echo "Access limited."
fi步骤2:比较字符串与==或者!=。引用变量以防止空值和空格破坏您的测试。这可以防止由未加引号的扩展引起的意外匹配。
user="alice"
target="alice"
if [[ "$user" == "$target" ]]; then
echo "Usernames match."
else
echo "Usernames differ."
fi步骤3:对内部整数使用数字运算符[[ ]]:-eq,-ne,-gt,-ge,-lt,-le。它们仅对数字进行操作,并避免字典顺序比较。
read -r -p "Enter a number: " n
if [[ "$n" -gt 10 ]]; then
echo "Greater than 10."
elif [[ "$n" -eq 10 ]]; then
echo "Equal to 10."
else
echo "Less than 10."
fi第4步:使用文件测试运算符检查文件。这些可以帮助您根据文件系统状态进行分支,而无需运行外部命令。
-f path: 常规文件存在。-d path: 目录存在。-e path:路径存在(任何类型)。-x path: 可执行文件存在。-r path/-w path:可读/可写。
path="./data.txt"
if [[ -f "$path" ]]; then
echo "File exists."
else
echo "Creating file..."
: > "$path"
fi第5步:结合条件与&&(和),||(或),和!(不是)。为了清晰和正确的优先级,将它们用括号分组。
file="./report.log"
size=5
# True when the file exists AND size is at least 5
if [[ -f "$file" ]] && [[ "$size" -ge 5 ]]; then
echo "Process report."
fi
# True when user is admin OR staff
role="staff"
if [[ "$role" == "admin" || "$role" == "staff" ]]; then
echo "Privileged."
fi
# Negation: path exists but is not a directory
if [[ -e "$file" && ! -d "$file" ]]; then
echo "Path is not a directory."
fi第6步:使用elif进行短路检查。一旦一个条件成立,后面的分支就会被跳过,从而加快评估速度并减少不必要的命令。
status="warning"
if [[ "$status" == "error" ]]; then
echo "Exit immediately."
exit 1
elif [[ "$status" == "warning" ]]; then
echo "Log and continue."
else
echo "All good."
fi方法 2:将整数与(( ))算术评估
步骤一:使用算术上下文进行数值逻辑。里面(( )),您可以编写类似数学的比较(<,>,==) 不引用变量。对于仅整数检查来说,这既简洁又快速。
a=12 b=8
if (( a > b )); then
echo "a is larger."
elif (( a == b )); then
echo "Equal."
else
echo "b is larger."
fi步骤2:直接在算术上下文中组合布尔运算符。这可以减少评估多个数字条件时的样板代码。
x=7 y=3 z=10
if (( (x > y) && (z >= 10) )); then
echo "Threshold met."
fi步骤3:验证输入。算术上下文将非数字值视为零。如果输入可能是非数字,请使用正则表达式测试来保护它[[ ]]在评估之前。
read -r n
if [[ "$n" =~ ^-?[0-9]+$ ]] && (( n >= 0 )); then
echo "Non-negative integer."
else
echo "Invalid number."
fi方法 3:使用 POSIX 便携式[ ]以获得更广泛的外壳兼容性
步骤一:当目标 shell 超出 Bash 时,首选单括号(例如,/bin/sh)。请记住[是一个命令:需要空格和引号。
#!/bin/sh
a="hello"
b="hello"
if [ "$a" = "$b" ]; then
echo "Match."
else
echo "No match."
fi步骤2:对整数和引号变量使用数字运算符以防止分词。这可以避免变量为空或包含空格时出现错误。
a=5
b=30
if [ "$a" -lt "$b" ]; then
echo "a is less than b."
fi步骤3:进行字典顺序字符串比较时<或者>,转义运算符以防止重定向。许多错误都源于忘记这一点。
x="apple" y="banana"
if [ "$x" \< "$y" ]; then
echo "apple comes before banana."
fi第4步:使用文件测试的方式与中相同[[ ]],但保留引用的所有内容以避免出现边缘情况。
file="./cfg.ini"
if [ -r "$file" ] && [ -w "$file" ]; then
echo "Config is readable and writable."
fi方法 4:将长链条替换为case用于基于值的分支
步骤一:使用case简化对单个变量的多个相等性检查。这减少了嵌套if匹配模式时阻止并提高可读性和速度。
read -r -p "Enter mode (start|stop|status): " mode
case "$mode" in
start) echo "Starting...";;
stop) echo "Stopping...";;
status) echo "Service is running.";;
*) echo "Unknown mode."; exit 1;;
esac步骤2:轻松匹配多种图案。这使您的逻辑保持紧凑并避免重复的变量比较。
level="warn"
case "$level" in
error|err) echo "Exit with failure."; exit 1;;
warn|warning) echo "Log warning.";;
info|debug) echo "Proceed normally.";;
*) echo "Unrecognized level.";;
esac方法五:正确测试多个条件并调试故障
步骤一:对布尔逻辑进行分组以反映您的真值表。例如,“需要 Z 或 X 和 Y”变为if [[ "$Z" == "TRUE" || ( "$X" == "TRUE" && "$Y" == "TRUE" ) ]]。括号阐明优先级并防止细微的错误。
X="TRUE" Y="FALSE" Z="TRUE"
if [[ "$Z" == "TRUE" || ( "$X" == "TRUE" && "$Y" == "TRUE" ) ]]; then
echo "Conditions met."
else
echo "Conditions not met."
fi步骤2:选择合适的运营商。使用==对于字符串和-eq对于整数。混合它们会导致不正确的分支(例如,字符串与-eq总是失败)。
步骤3:在测试中引用变量扩展,尤其是使用单括号。引用可以避免变量为空时发生崩溃,并防止对文件系统条目进行通配符扩展。
第4步:当结果看起来错误时追踪逻辑。启用 xtrace 可以在 Bash 评估时查看每个扩展命令和条件。
#!/usr/bin/env bash
set -x # turn on trace
# ... your conditionals here ...
set +x # turn off trace第5步:保持脚本的一致性和可读性。正文下方缩进then/else,在括号周围留出空格,并支持在错误分支上尽早退出以减少嵌套。
参考:常见测试操作员一览
此快速列表可帮助您选择适合该作业的操作员。
- 字符串:
==,!=,-n var(长度> 0),-z var(空的)。 - 整数:
-eq,-ne,-gt,-ge,-lt,-le;或使用(( ))和<,>,==. - 文件:
-f(常规的),-d(目录),-e(存在),-x(可执行文件),-r(可读),-w(可写)。 - 逻辑:
&&(和),||(或者),!(不是);与组( ... )里面[[ ]].
通过正确的测试形式、正确的运算符和一致的引用,您的 Bash 条件每次都会执行预期的分支。保持[[ ]]对于 Bash 脚本,请使用(( ))对于数学,然后回到[ ]仅当必须具有便携性时。





