执行 Shell 脚本时出现 syntax error near unexpected token `fi'
数据小陈
结论
脚本中的 if ... then ... fi 结构没有明显的语法问题。更可能的原因是文件使用了 Windows 风格的 CRLF 换行符,而当前执行环境需要 Unix 风格的 LF。
隐藏的 \r 会让 Shell 读到 fi\r,因此无法把它识别为关键字 fi,并报错:
syntax error near unexpected token `fi'
此前出现的 command not found 和显示错位的文件名,通常也是 \r 干扰终端输出造成的。
修复方法
把文件的换行格式从 CRLF 转换为 LF。
如果系统已安装 dos2unix,可以执行:
dos2unix run_billing.sh
也可以用 sed 删除每行末尾的回车符:
sed -i 's/\r$//' run_billing.sh
macOS 自带的 sed 参数稍有不同:
sed -i '' $'s/\r$//' run_billing.sh
使用 VS Code、Vim 等编辑器时,也可以把行尾格式从 CRLF 改为 LF,再重新保存文件。
转换完成后重新执行:
sh run_billing.sh 062000002015.00
建议修改后的脚本
原脚本还有一处参数判断不一致:用法示例只传入一个参数,代码却要求参数数量为两个。按照示例,应该检查是否恰好传入一个参数。
#!/bin/sh
PRG_NAME=${0##*/}
NARGS=$#
if [ "$NARGS" -ne 1 ]; then
echo "$PRG_NAME: error: incorrect number of arguments ($NARGS)"
echo "Usage: $PRG_NAME [Time]"
echo "Time format - pin_virtual_time format. e.g. 062000002015.00"
echo "Example: sh run_billing.sh 062000002015.00"
exit 1
fi
echo "Run Billing script - pin_bill_day"
pin_virtual_time -m2 "$1"
pin_bill_day
这版脚本还做了以下调整:
- 使用
[ "$NARGS" -ne 1 ],确保只接收一个参数。 - 为变量加上双引号,避免变量为空或包含特殊字符时被意外解析。
- 使用
${0##*/}获取当前脚本名,避免PRG_NAME未定义。 - 删除行尾多余的分号,使写法更符合常见的 Shell 风格。
如果转换换行符后仍然报错
可以显示隐藏字符,检查文件中是否仍有 \r:
sed -n 'l' run_billing.sh
如果行尾显示为 \r$,文件中仍然存在 Windows 回车符。
还可以只检查语法,不实际执行脚本:
sh -n run_billing.sh
同时确认脚本由兼容 POSIX 语法的 Shell 执行。当前脚本使用标准 /bin/sh 语法,无需改成 Bash。如果要直接运行脚本,还需要添加执行权限:
chmod +x run_billing.sh
./run_billing.sh 062000002015.00
核心修复是把脚本保存为 Unix LF 换行格式。
备注:内容仅供参考。
