VIM搜索/替换模式

时间:2013-02-22 21:57:14

标签: vim

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

a)该行包含str1

b)该行还包含str2

c)该行不包含str3

在这样的一行上,我确实想用yyy替换xxx

3 个答案:

答案 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的答案中使用示例的结果相同,它将处理gstr1str2str3的任何顺序。
我再说一遍,如果由于某种原因,某个功能不是替代品,那么这是另一种选择。据我了解OP,例如在他的情况下,xxx总是在str2之后,因此对于这样的情况(可能更多的学术兴趣)来说,这更像是一般解决方案。