在子shell/函数内设置extglob时Bash脚本出现语法错误的问题求助
解决Bash中子shell/函数内设置
extglob仍报语法错误的问题 这其实是Bash的语法解析顺序导致的经典坑,很多人都会被这个现象搞懵!
问题根源
Bash执行脚本的流程是:先完成整个脚本的语法解析,再逐行执行命令。当你在子shell或者函数内部设置shopt -s extglob时,这个设置是在执行阶段才生效的,但脚本里那些依赖extglob的模式(比如!(*.txt)这类扩展通配符),在解析阶段就已经被Bash当成无效语法处理了——这时候extglob还没开启呢!
哪怕你在函数里加了shopt extglob验证,显示选项已经开启,那也是执行到那一行后的状态,无法回溯修正之前已经解析错误的语法。
而全局设置extglob能正常工作,是因为脚本开头的shopt -s extglob在解析阶段之前就已经生效,Bash知道要启用扩展通配符语法,所以能正确解析那些模式。
解决方案
这里有两种靠谱的处理方式:
1. 全局提前启用extglob
如果你的脚本整体都需要用到扩展通配符,直接在脚本最顶部添加开启命令,一劳永逸:
#!/bin/bash shopt -s extglob # 后面的函数、子shell里都可以直接用extglob模式 my_func() { rm !(*.txt) } my_func
2. 用eval延迟语法解析
如果不想全局开启extglob,可以用eval让依赖extglob的命令在选项生效后再完成解析:
- 函数内的写法:
my_func() { shopt -s extglob # 把需要extglob的命令用单引号包裹,交给eval执行 eval 'rm !(*.txt)' }
- 子shell内的写法:
( shopt -s extglob eval 'rm !(*.txt)' )
eval会在执行阶段才解析引号内的字符串,这时候extglob已经开启,Bash就能正确识别扩展通配符了。
内容的提问来源于stack exchange,提问作者Antoine Cotten
相关产品推荐
相关产品推荐

