Bash 4.1.2(2):如何在for循环中实现正则反向匹配?
解决Bash遍历不含指定字符串目录的问题
你的问题出在Bash的路径扩展(glob)不支持PCRE风格的正则表达式——你写的^((?!unicredit*).)*$是正则语法,但Bash默认的通配符是glob模式,不识别这种负向前瞻语法,所以会报语法错误。
下面给你几种可行的修改方案:
方案1:使用Bash扩展通配符(extglob)
这是最原生的Bash解决方案,开启extglob后可以直接用排除式匹配:
- 先开启扩展通配符(如果没开的话):
shopt -s extglob
- 执行遍历命令:
for i in /tmp/scripts/bash/test/!(*unicredit*); do echo FOUND $i; done
这里的!(*unicredit*)是extglob的语法,表示匹配所有不包含"unicredit"的条目,完全符合你的需求,会输出:
FOUND /tmp/scripts/bash/test/par_q FOUND /tmp/scripts/bash/test/swx_i FOUND /tmp/scripts/bash/test/swx_r
方案2:用find命令过滤(更安全,适合复杂场景)
如果不想依赖extglob,或者需要处理含特殊字符的文件名,用find更可靠:
find /tmp/scripts/bash/test/ -maxdepth 1 -type d ! -name "*unicredit*" ! -path "/tmp/scripts/bash/test/" | while read -r dir; do echo FOUND "$dir"; done
参数解释:
-maxdepth 1:只遍历目标目录的直接子目录,不深入递归-type d:只筛选目录(排除文件)! -name "*unicredit*":排除名字包含"unicredit"的目录! -path ...:排除目标目录本身(避免输出/tmp/scripts/bash/test/)
方案3:结合ls和grep(简单但需注意文件名空格)
如果场景简单,也可以用管道配合grep过滤:
ls -d /tmp/scripts/bash/test/* | grep -v "unicredit" | while read -r dir; do echo FOUND "$dir"; done
-v参数表示反向匹配,即排除包含"unicredit"的行。不过这种方法如果文件名包含空格或特殊字符可能出问题,优先推荐前两种方案。
为什么原命令报错?
Bash的for循环里的路径是用glob模式匹配的,而不是正则表达式。你写的^、(?!...)这些都是PCRE正则的语法,Bash glob完全不识别,会把括号当成命令语法的一部分,所以触发syntax error near unexpected token '('的错误。
内容的提问来源于stack exchange,提问作者kamokoba
相关产品推荐
相关产品推荐

