如何使用以下条件进行VIM搜索/替换:
a)该行包含str1
b)该行还包含str2
c)该行不包含str3
在这样的一行上,我确实想用yyy替换xxx
答案 0 :(得分:1)
正则表达式不能很好地处理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/
请注意,只能为您的示例工作编写更短的内容,但我希望它是安全的。
答案 1 :(得分:1)
在此之后的某个时刻,这将替换包含字符串()
和字符串return
的文件的每一行中的aLib
字符串:
:%s/return.*aLib.*\zs()\ze/(aHandle)/
%
是命令的操作范围,包括文件中的所有行。
\zs
表示替换字符串的开头,\ze
表示结束字符串。
如果必须每行替换多个实例,请在最后g
之后的命令末尾添加/
。如果您希望确认每次替换,请将c
标记放在最后。
假设()
字符串永远不存在,如果aHandle
存在,则此命令不会完全回答您的问题,但根据评论中提供的示例,这可能符合您的需求。
答案 2 :(得分:0)
我认为 @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
”,前面的.*
对&
和@=
都很重要工作&
之前和之后的&
模式,与使用“或”的|
不同,两种模式必须从同一个地方开始,这就是为什么在.*
,:h \&
str1/2
的原因
@=
之前(在括号中)的原子应该存在,但是模式不包含在匹配中,但是原子必须从行的开头开始才能使其工作({{1}确保这一点。).*
任何字符0或更多(“不贪婪”),.{-}
而不是{-}
,如果应该替换多次出现*
,则非常重要在这种情况下足够xxx
标志)g
设置匹配的开头(替换内容)。\zs
最后,替换xxx
将此匹配替换为/yyy/
yyy
所有出现的行这与在@ Kent的答案中使用示例的结果相同,它将处理g
,str1
,str2
和str3
的任何顺序。
我再说一遍,如果由于某种原因,某个功能不是替代品,那么这是另一种选择。据我了解OP,例如在他的情况下,xxx
总是在str2
之后,因此对于这样的情况(可能更多的学术兴趣)来说,这更像是一般解决方案。