1

如何使用以下条件进行 VIM 搜索/替换:

a) 该行包含 str1

b)该行还包含 str2

c) 该行不包含 str3

在这样一条线上,我确实想用 yyy 替换 xxx

4

3 回答 3

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/

请注意,它可以写得更短,仅用于您的示例工作,但我希望它是安全的。

于 2013-02-22T22:51:38.043 回答
1

这将替换()包含该字符串的文件的每一行中的字符串return,并aLib在之后的某个时间点替换该字符串:

:%s/return.*aLib.*\zs()\ze/(aHandle)/

%是命令的操作范围,包括文件中的所有行。

\zs表示被替换字符串的开始并\ze表示它的结束。

如果每行必须替换多个实例,g请在命令末尾的最后一个/. 如果您想确认每个替换,请将c标志放在末尾。

通过假设()如果存在则字符串永远不aHandle存在,此命令不能准确回答您的问题,但根据评论中提供的示例,这可能符合您的需求。

于 2013-02-22T22:51:46.383 回答
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”,前面.*对于两者&@=工作都很重要
    • &&必须存在前后模式,与|使用“或”不同,两种模式必须从同一位置开始,这就是为什么.*使用 before str1/2:h \&
    • @=前面的原子(在括号中)应该存在,但模式不包括在匹配中,但是原子必须从行的开头开始才能起作用(.*确保这一点)。
  • .{-}任何字符 0 或更多(“不贪婪”),如果应该替换不止一次的出现,{-}而不是*很重要(在这种情况下,标志还不够)xxxg
  • \zs设置比赛的开始(替换什么)。
  • xxx最后,要替换的字符串
  • /yyy/将匹配替换为yyy
  • g在线上的所有事件

这给出了与使用@Kent 答案中的示例相同的结果,它将处理、str1和的任何顺序。 我再说一遍,如果由于某种原因一个函数不是一个替代方案,这是一个替代方案。据我了解 OP,例如,在他的情况下总是如此,所以这对于这种情况来说是一个更通用的解决方案(也许更多的学术兴趣)。str2str3xxx
str2str1

于 2013-02-23T01:53:21.327 回答