如何使用以下条件进行 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 或更多(“不贪婪”),如果应该替换不止一次的出现,{-}
而不是*
很重要(在这种情况下,标志还不够)xxx
g
\zs
设置比赛的开始(替换什么)。xxx
最后,要替换的字符串/yyy/
将匹配替换为yyy
g
在线上的所有事件这给出了与使用@Kent 答案中的示例相同的结果,它将处理、str1
和的任何顺序。
我再说一遍,如果由于某种原因一个函数不是一个替代方案,这是一个替代方案。据我了解 OP,例如,在他的情况下总是如此,所以这对于这种情况来说是一个更通用的解决方案(也许更多的学术兴趣)。str2
str3
xxx
str2
str1