Bash脚本for循环疑似被跳过 统计变量始终为0如何解决
问题描述
编写了一段Bash for循环代码,用于统计系统中尚未安装的工具数量,代码如下:
#!/bin/bash DIALOG_INSTALLED=$(which dialog) BREW_INSTALLED=$(which brew) TELNET_INSTALLED=$(which telnet) UNINSTALLED_TOOLS=0 for installed_for in $DIALOG_INSTALLED $BREW_INSTALLED $TELNET_INSTALLED; do if [[ -z $installed_for ]]; then let "$UNINSTALLED_TOOLS+=1" fi done echo $UNINSTALLED_TOOLS
运行代码时出现异常:$UNINSTALLED_TOOLS的输出值始终为0。在for循环前后分别添加UNINSTALLED_TOOLS=3的赋值语句测试,两次调整后变量最终输出均为3,确认问题出在for循环内部——代码似乎直接跳过循环执行,全程无任何语法报错。
问题根源
核心原因是Bash的变量展开规则:
未加引号引用的空变量在单词拆分阶段会被直接移除,不会作为空字符串成为循环的迭代项。
当对应工具未安装时,which 工具名没有输出,对应的XXX_INSTALLED变量值为空。如果有任意一个变量为空,展开后不会产生对应的循环迭代;如果三个工具全未安装,三个变量全为空,for行展开后in关键字后没有任何有效内容,循环体一次都不会执行,计数变量自然始终保持初始值0。
另外原代码还有两处不规范的点:
let "$UNINSTALLED_TOOLS+=1"中给算术表达式里的变量加$属于多余写法,let后可直接写变量名做运算- 检查命令是否存在时,
which的跨环境兼容性较差,部分系统下可能出现异常输出,不推荐在脚本中使用
修复方案
直接维护待检查的工具名列表,逐个遍历检查命令是否存在即可,修复后的代码如下:
#!/bin/bash # 待检查的工具清单 CHECK_TOOLS=("dialog" "brew" "telnet") UNINSTALLED_TOOLS=0 for tool in "${CHECK_TOOLS[@]}"; do # 丢弃command -v的输出,仅通过返回值判断命令是否存在 if ! command -v "$tool" >/dev/null 2>&1; then let UNINSTALLED_TOOLS+=1 fi done echo "$UNINSTALLED_TOOLS"
内容的提问来源于stack exchange,提问作者Caecilius-rgb
相关产品推荐
相关产品推荐

