sed无法替换匹配行:正则经grep验证有效但替换失效
解决sed首次匹配行替换未生效的问题
看起来你遇到的核心问题是sed默认使用基本正则表达式(BRE),而你用来匹配的正则是扩展正则表达式(ERE)语法——这就是为什么grep加-E能匹配到目标行,但sed替换却没生效的原因。
问题根源分析
你用grep -E时启用了扩展正则,其中\s(匹配空白字符)和+(匹配一次或多次)都是ERE的语法;但sed默认是BRE模式,这些语法不被识别,导致你的正则表达式在sed里根本匹配不到目标行,自然也就不会执行替换操作。
两种可行的解决方案
方案1:让sed使用扩展正则(推荐)
给sed加上-E参数,启用扩展正则模式,这样就能直接复用你在grep里验证过的正则了:
P='auth sufficient pam_unix.so nullok try_first_pass' sed -E "0,/^\s*auth\s+sufficient\s+pam_unix\.so.*$/s//${P}/" input
执行后再用grep验证,就能看到替换后的正确结果:
sed -E "0,/^\s*auth\s+sufficient\s+pam_unix\.so.*$/s//${P}/" input | grep -E '^\s*auth\s+sufficient\s+pam_unix\.so.*$' # 输出:auth sufficient pam_unix.so nullok try_first_pass
方案2:修改正则为基本正则兼容语法
如果你不想用-E参数,可以把正则转换成BRE兼容的格式:
- 把
\s替换成BRE支持的[[:space:]]; - 把
+转义成\+(因为BRE中+是普通字符,转义后才表示“一次或多次”)。
对应的sed命令:
P='auth sufficient pam_unix.so nullok try_first_pass' sed "0,/^[[:space:]]*auth[[:space:]]\+sufficient[[:space:]]\+pam_unix\.so.*$/s//${P}/" input
这个命令同样能完成首匹配行的替换。
额外说明
如果你的sed是GNU sed版本,也可以用-r参数代替-E(两者功能一致);但-E是POSIX标准的参数,兼容性更好。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

