Linux中grep、sed、awk默认用BRE/ERE而非PCRE,不支持\d、\s、+等;需grep -P/sed -E/awk ERE语法适配;文件名匹配应使用glob或find -regex;变量截取用[[ =~ ]]或sed/awk,不可混用正则与glob。

grep、sed、awk 用的不是 PCRE 正则
Linux Shell 中原生命令(grep、sed、awk)默认不支持 \d、\s、+(贪婪量词)、?(非贪婪)、(?:...) 这类 PCRE 风格语法。它们用的是 BRE(Basic Regular Expressions)或 ERE(Extended Regular Expressions),取决于是否加 -E 参数。
常见踩坑现象:grep "\d+" file.txt 不会匹配数字,因为 \d 在 BRE/ERE 中无定义;sed "s/a+/A/g" 也无效——+ 默认不被识别为量词。
-
grep -E启用 ERE:支持+、?、|、()(无需反斜杠转义) -
grep -P才启用 PCRE(需 GNU grep ≥ 2.20,且系统装有 PCRE 库),此时\d、\s、(?i)等才可用 -
sed -E(GNU sed 或 macOS 10.15+ 的sed -E)启用 ERE;老版 macOSsed只认-E,不认-r -
awk默认就是 ERE 行为,gsub(/a+/, "X")可直接用+
文件名匹配别用正则,用 glob 就够了
Shell 对命令行参数的展开(如 ls *.log)走的是 pathname expansion(glob),不是正则。写成 ls [0-9]+.log 或 ls \d{4}.log 会报错:No such file or directory,因为 shell 根本不解析这些为正则。
真正需要正则匹配文件名时,得靠 find + -regex(注意:它匹配的是**完整路径**,不是 basename)或 ls | grep -E 这类组合。
-
find . -regex ".*/[0-9]{4}\.log":匹配形如./2023.log的路径(注意.*/前缀和字面点要转义) -
ls | grep -E "^[0-9]{4}\.log$":更直观,但只处理当前目录下文件名(不含路径) -
shopt -s extglob后可用ls @(2023|2024).log这类扩展 glob,但仍是 glob,不是正则
变量替换里的 ${var##pattern} 不支持正则,只支持通配符
Bash 参数扩展(Parameter Expansion)中的 ${var#...}、${var%%...} 等语法,pattern 是 shell glob,不是正则。写 ${str##[0-9]+} 或 ${str##\d+} 会原样返回,不会截掉数字前缀。
想用正则做字符串裁剪,必须换工具:sed、awk 或 Bash 3.2+ 的 [[ $str =~ regex ]] 捕获组。
- 错误写法:
filename="log_20230405.txt"; echo ${filename##[0-9]*}→ 实际匹配的是[0-9]*glob(等价于任意单个数字开头的最长串),不可控 - 正确做法(用
[[ ]]捕获):[[ $filename =~ _([0-9]{8})\. ]] && echo "${BASH_REMATCH[1]}"→ 提取 8 位日期 - 或用
sed -E 's/.*_([0-9]{8})\.txt/\1/',语义明确,跨 shell 兼容性更好
脚本里该选 [[ =~ ]] 还是 grep -q?
Bash 内置的 [[ string =~ regex ]] 支持 ERE(不支持 PCRE),速度快、无子进程;但它的 regex 是字面字符串,不能拼接变量(除非用间接引用或 eval,有风险),且不同 Bash 版本对捕获组支持不一(BASH_REMATCH 从 3.2 起稳定)。
grep -q 更通用、行为确定,适合复杂逻辑或需兼容 dash/sh 的场景,但每次调用都 fork 进程,高频循环中可能拖慢脚本。
- 简单判断用
[[ $line =~ ^[[:space:]]*# ]](跳过空行和注释)——安全、高效 - 要动态构造正则(比如从配置读 pattern),优先用
printf '%s' "$line" | grep -Eq "$pattern",避免eval - 注意:
[[ =~ ]]中的^和$锚定整行;而grep默认也是全行匹配,无需额外加-x,除非你明确要“完全相等”
正则在 Shell 里从来不是“开箱即用”的工具,每个命令的引擎、锚定规则、转义层级都不同。最省事的方式,是先确认你要匹配的对象类型(文件名?行内容?变量值?),再选对工具,而不是强行把一个正则套到所有地方。


















