Linux命令行sed正则表达式*量词匹配逻辑咨询
r*限定符的匹配逻辑:为什么echo f | sed 's/r*/x/g'输出xfx? 嘿,这个问题正好戳中了正则表达式里*限定符最容易让人困惑的点——它不仅匹配前导元素的多次出现,还匹配零次出现,再加上sed全局匹配的遍历逻辑,就出现了看起来有点反直觉的结果。咱一步步拆解清楚:
核心前提:*限定符的本质
首先得牢牢记住:r*表示匹配0个或多个连续的r。重点是「0个」也完全符合匹配条件!这是很多人刚开始学正则时容易忽略的点——你以为它只会找有r的地方,但它连没有r的“空位置”也会匹配。
拆解echo f | sed -re 's/r*/x/g'的处理流程
原字符串是单个字符f,sed的全局匹配g会从头到尾扫描所有可能的匹配位置,包括字符的前后空位置。具体步骤如下:
第一步:匹配字符串开头的空位置
sed从字符串最开头(^位置)开始尝试匹配r*:这里没有任何r,所以匹配「0个r」(成功匹配),替换成x。此时字符串变成xf,sed的指针会移动到f的位置(因为是零长度匹配,sed会强制前进1位,避免无限循环)。第二步:匹配
f所在位置的空匹配
指针现在指向f,尝试匹配r*:f不是r,所以还是只能匹配「0个r」(成功匹配),替换成x。此时字符串变成xfx,指针移动到f的下一位(也就是字符串末尾)。第三步:到达字符串末尾,停止匹配
指针已经到了字符串最后,再尝试匹配r*虽然还是能匹配0个r,但sed没有更多位置可以前进,所以停止处理。最终输出就是xfx。
再看echo fd | sed -re 's/r*/x/g'的情况
字符串是fd,逻辑和上面完全一致,只是多了一个字符:
- 开头空位置匹配0个r → 替换成
x,字符串变成xfd,指针移到f。 f位置匹配0个r → 替换成x,字符串变成xfxd,指针移到d。d位置匹配0个r → 替换成x,字符串变成xfxdx,指针移到末尾,停止。
所以最终输出是xfxdx。
对比你理解的echo rrr | sed -re 's/r*/x/g'
这个例子里,r*匹配了连续3个r(也就是多次出现的情况),替换成x后,指针直接跳到了字符串末尾(因为匹配了长度为3的内容)。此时再尝试匹配r*虽然能匹配0个r,但没有位置可以前进了,所以不会再替换,最终只输出x。
总结关键要点
- 别忽略
*的「零次匹配」特性,这是这类反直觉结果的核心原因; - sed的
g全局匹配会遍历所有可能的位置,包括字符之间、首尾的空位置; - 遇到非匹配字符时,
r*会匹配零次(空字符串),sed为了避免无限循环,会强制指针前进1位。
内容的提问来源于stack exchange,提问作者hugo

