共计 1490 个字符,预计需要花费 4 分钟才能阅读完成。
背景痛点
作为 Shell 脚本新手,第一次遇到-bash: syntax error near unexpected token(` 错误时往往一头雾水。这个报错通常出现在以下场景:

- 在命令行或脚本中误用括号(特别是
(和)) - 特殊字符未正确转义
- 命令替换语法使用不当
Shell 对括号的使用有严格规定,不同类型的括号(圆括号、方括号、花括号)在 Shell 中有完全不同的含义。新手很容易混淆它们的用法,导致脚本无法正常执行。
技术解析:Shell 中括号的不同含义
在深入解决方案前,我们先理清 Shell 中各种括号的核心用途:
- 圆括号
() - 命令组:在子 shell 中执行一组命令,如
(cd /tmp && ls) - 命令替换:旧式语法(已被反引号
``和$()取代) -
数组初始化:如
array=(a b c) -
方括号
[] - 条件测试:等同于
test命令,如[-f file.txt] -
字符类匹配:在正则表达式中使用
-
花括号
{} - 命令分组:在当前 shell 执行一组命令,如
{cd /tmp; ls;} - 序列表达式:如
echo {1..10} - 变量扩展:如
${variable}
混淆这些用法是导致 unexpected token 错误的常见原因。
解决方案:3 种典型错误案例
案例 1:未转义的特殊字符
错误代码:
echo (Hello World)
错误分析:
Shell 将 ( 解释为特殊字符,但这里只是想要输出普通括号。
修正代码:
echo "(Hello World)" # 用引号包裹
或者
echo \(Hello World\) # 使用转义字符
案例 2:引号使用不当
错误代码:
name="John (Smith)"
grep "($name)" file.txt
错误分析:
变量展开后括号成为特殊字符,应该对正则表达式特殊字符进行转义。
修正代码:
name="John (Smith)"
grep "\\($name\\)" file.txt # 转义正则元字符
案例 3:命令替换语法错误
错误代码:
date=$(date)
echo "Current date is: ($date)"
表面看起来没问题,但如果 date 命令包含特殊字符就会出错。更安全的做法是:
修正代码:
date=$(date)
echo "Current date is: ($date)" # 确保变量值用引号包裹
避坑指南:5 条 Shell 脚本括号使用黄金法则
- 引号优先原则:不确定是否特殊字符时,先用双引号包裹
- 转义显式原则 :在正则表达式或需要字面量时,对
() [] {}等特殊字符进行转义 - 空格敏感原则 :
[]测试语句内必须保留空格,如[-f file] - 类型明确原则 :分清算术扩展
$(())、命令替换$()和数组()的区别 - 工具辅助原则 :使用
shellcheck等工具提前发现语法问题
进阶建议:使用 shellcheck 进行静态检查
安装和使用方法:
# Ubuntu/Debian
sudo apt install shellcheck
# macOS
brew install shellcheck
# 检查脚本
shellcheck your_script.sh
这个工具能识别常见的语法错误,包括括号使用不当的问题,并给出专业建议。
互动思考题
-
以下代码为什么会报错?如何修正?
for i in (1 2 3); do echo $i; done -
假设你需要查找包含
ERROR (code 5)的日志行,以下哪种 grep 写法最可靠?为什么?grep "ERROR (code 5)" file.log grep 'ERROR (code 5)' file.log grep "ERROR \\(code 5\\)" file.log
通过实际动手解决这些问题,你会对 Shell 中的括号使用有更深刻的理解。遇到报错时,不要慌,仔细检查特殊字符的处理方式,大多数问题都能迎刃而解。
正文完
