如何使用以下条件进行 VIM 搜索/替换:
a) 该行包含 str1
b)该行还包含 str2
c) 该行不包含 str3
在这样一条线上,我确实想用 yyy 替换 xxx
正则表达式处理得不是and, not很好。有办法做到这一点,但有点棘手。一个非常简单的功能可以解决您的问题:
function! Rep()
let l = getline('.')
if stridx(l, 'str1')>=0 && stridx(l,'str2') >=0 && stridx(l,'str3')<0
execute 's/xxx/yyy/g'
endif
endfunction
你可以
.vimrc文件中。foo.vim文件中并使用 vim 类型打开它:so % 然后打开您的目标文件,输入:%call Rep()您将看到的示例:
str1 str2 str3 xxx
str3 str2 xxx
str2 xxx
*str1 str2 xxx
*xxx str2 xxx str2 xxx str1
将更改为:
str1 str2 str3 xxx
str3 str2 xxx
str2 xxx
*str1 str2 yyy
*yyy str2 yyy str2 yyy str1
我认为在该函数中将 str1,str2,xxx,yyy 替换为您的实际值对您来说并不难,是吗?
编辑
您真正的问题似乎比您所描述的问题要容易得多。试试这一行:
:%s/\(\s*return\s*aLib\.[^(]\+(\)\s*\()\)/\1aHandle\2/
请注意,它可以写得更短,仅用于您的示例工作,但我希望它是安全的。
这将替换()包含该字符串的文件的每一行中的字符串return,并aLib在之后的某个时间点替换该字符串:
:%s/return.*aLib.*\zs()\ze/(aHandle)/
%是命令的操作范围,包括文件中的所有行。
\zs表示被替换字符串的开始并\ze表示它的结束。
如果每行必须替换多个实例,g请在命令末尾的最后一个/. 如果您想确认每个替换,请将c标志放在末尾。
通过假设()如果存在则字符串永远不aHandle存在,此命令不能准确回答您的问题,但根据评论中提供的示例,这可能符合您的需求。
我认为@Kent的答案(函数)在进行复杂搜索/替换时是“最正确的”。后面改比较容易,过段时间也能理解,写起来也比这个快。但我认为如果可以使用“oneliner”来做到这一点会很有趣。
我欢迎对此不起作用的评论,如果可能的话,我觉得自己很有趣,而不是如果它是“最佳解决方案”。
原始问题中描述的所有情况的“oneliner”。
:v/str3/s/\v(.*str1&.*str2)@=.{-}\zsxxx/yyy/g
解释:
:v/str3/所有不包含“ str3”的行s/代替\v“非常神奇”(不必逃避正则表达式,如{}),:h \v(.*str1&.*str2)@=积极前瞻,:h \@=
.*str1任何字符 0 或更多(“贪婪”)后跟“ str1”,前面.*对于两者&和@=工作都很重要&&必须存在前后模式,与|使用“或”不同,两种模式必须从同一位置开始,这就是为什么.*使用 before str1/2,:h \&@=前面的原子(在括号中)应该存在,但模式不包括在匹配中,但是原子必须从行的开头开始才能起作用(.*确保这一点)。.{-}任何字符 0 或更多(“不贪婪”),如果应该替换不止一次的出现,{-}而不是*很重要(在这种情况下,标志还不够)xxxg\zs设置比赛的开始(替换什么)。xxx最后,要替换的字符串/yyy/将匹配替换为yyyg在线上的所有事件这给出了与使用@Kent 答案中的示例相同的结果,它将处理、str1和的任何顺序。
我再说一遍,如果由于某种原因一个函数不是一个替代方案,这是一个替代方案。据我了解 OP,例如,在他的情况下总是如此,所以这对于这种情况来说是一个更通用的解决方案(也许更多的学术兴趣)。str2str3xxxstr2str1