syntax error near unexpected token 错误主因是 shebang 缺失/错误或 windows 换行符(^m)污染,需用 head -n1 | cat -a 检查、dos2unix 修复,并确认 shebang 路径存在;语法检查应使用对应 shell 的 -n 选项。

看到 syntax error near unexpected token 先看 shebang 和换行符
这个错误几乎从不表示语法写错了,而是 shell 解析器根本没按你预期的方式启动。最常见原因是脚本第一行的 #!/bin/bash 缺失、拼错,或被 Windows 换行符(\r\n)污染——此时 shell 实际读到的是 #!/bin/bash\r,把 \r 当作非法 token 报错。
- 用
head -n1 your_script.sh | cat -A查看首行真实字符:如果末尾显示^M,就是 DOS 换行符 - 修复用
dos2unix your_script.sh,或sed -i 's/\r$//' your_script.sh - 确认 shebang 路径存在:
ls -l /bin/bash;某些最小化系统只有/bin/sh,写成#!/bin/bash却用sh your_script.sh执行也会触发该错误
用 bash -n 静态检查语法,别直接运行
bash -n script.sh 会跳过执行,只做语法解析,能快速定位哪一行有括号、引号或重定向符号不匹配。注意它只检查当前 shell 类型(比如 #!/bin/sh 的脚本要用 sh -n,用 bash -n 可能放过 sh 不支持的语法)。
- 常见诱因:
if [ $var = "ok" ]; then中$var为空导致变成if [ = "ok" ],缺少左操作数 - 函数定义漏了括号:
myfunc { echo 1; }应为myfunc() { echo 1; } - Here-document 结束标识符后多了空格或 tab:
cat 后面不能跟任何字符
交互式调试:用 set -x 看实际执行流
如果语法检查通过但运行时报错,大概率是变量展开或命令替换导致某行最终生成了非法结构。在脚本开头加 set -x,shell 会打印每条实际执行的命令(含变量展开后结果),一眼就能看出哪条语句被解析成了带 unexpected token 的样子。
- 临时启用:
bash -x ./script.sh,不用改脚本 - 避免干扰:在关键段落前后加
set -x/set +x,缩小输出范围 - 特别注意
$()或反引号包裹的命令输出里是否含未转义的换行、括号或重定向符
注意不同 shell 对语法的容忍度差异
同一段脚本,在 bash 下能跑,用 sh 执行就报 unexpected token,很可能是用了 bash 特有语法。比如 [[ ]]、let、数组 arr=(a b)、大括号扩展 echo {1..3} 都不被 POSIX sh 支持。
- 检查执行方式:
./script.sh依赖 shebang;sh script.sh强制用 sh,无视 shebang - 确认目标环境 shell:Alpine 默认用
ash,CentOS Stream 9 默认bash,但容器里常被替换成dash - 可移植写法:用
[ ]替代[[ ]],用case替代正则匹配,避免$(( ))外的算术扩展
真正棘手的情况是错误出现在动态生成的代码里——比如用 eval 拼接字符串,或从配置文件读取值后直接插进 if 判断。这时候 set -x 输出里的那条“爆炸”的命令,才是唯一可信的线索。











