如何在Vim中修剪匹配foo.*bar模式内容的最后5个字符?
解决Vim中修剪
foo.*bar匹配内容最后5个字符的问题 你之前用的:g/foo.*bar/norm $5X没达到预期,其实是踩了个小坑——norm $会直接跳到整行的末尾,而不是你要的foo.*bar这段匹配内容的尾部,所以删的是行尾的5个字符,根本没碰目标文本。
要精准修剪匹配内容的最后5个字符,用Vim的:substitute(简称s)命令才是正解,它支持正则捕获和表达式替换,能完美搞定这个需求:
核心解决方案:表达式替换法
这个方法不管匹配内容的长度是多少,都能精准去掉最后5个字符,非常灵活:
:%s/foo.*bar/\=strpart(submatch(0), 0, len(submatch(0))-5)/
命令拆解:
%:让命令作用于所有行(如果只想处理包含foo.*bar的行,换成:g/foo.*bar/s//\=strpart(submatch(0), 0, len(submatch(0))-5)/就行,s//会复用前面g的匹配模式,不用重复写)\=:告诉Vim后面是一段表达式,不是普通字符串submatch(0):指代整个匹配到的foo.*bar内容len(submatch(0))-5:计算出要保留的内容长度(总长度减去要删掉的5个字符)strpart(...):从匹配内容的开头,截取到计算好的长度,也就是去掉最后5个字符后的结果
进阶:避免短内容被误删
如果担心有些匹配内容的长度≤5,执行上面的命令会把整个内容删掉,可以加个判断逻辑,只处理长度大于5的匹配:
:%s/foo.*bar/\=len(submatch(0))>5 ? strpart(submatch(0), 0, len(submatch(0))-5) : submatch(0)/
这样长度≤5的匹配内容会保持原样,不会被修改。
为什么原命令不行?
再啰嗦一句,:g/foo.*bar/norm $5X的逻辑是:找到所有包含foo.*bar的行,然后在每行执行普通模式命令$(跳行尾)+5X(删5个字符)——它完全没关注foo.*bar这个匹配块的位置,只认行尾,所以自然达不到你的要求啦。
内容的提问来源于stack exchange,提问作者umeshr
相关产品推荐
相关产品推荐

