尽管vim中有任何正则表达式字符,我如何替换所选内容?

时间:2013-10-23 02:00:25

标签: regex vim

在以下代码中:

int return_int_func() { return 0; }
float fv = return_int_func();

显然,编译器会警告我fv可能会因为自动转换而失去精确度。面对很多这样的事情,我想用替换命令替换所有的东西。简而言之,我想要这个:

float fv = static_cast<float>(return_int_func());

但真实代码有很多这样的形式:

float fv = obj.int_field;
float fv = obj->load_int_field("name");
float fv = xx.yy->zz;

我想选择我的目标(obj.int_fieldobj->load_int_field("name")xx.yy->zz)并将其替换为static_cast<float>(\1)。我试过这个:

:'<,'>s/\%V/static_cast<float>(&)/g

但是vim用static_cast...替换所选单词中的所有字符,这根本不是我想要的。然后我尝试了这个:

:'<,'>s/\(\%V\)/static_cast<float>(\1)/g

Vim也做同样的事情。我不知道如何用我的模式替换整个内容(尽管有任何正则表达式字符)。有什么建议?

5 个答案:

答案 0 :(得分:1)

让我试着解释一下你的问题:你想要Visual选择一些文本,然后执行替换,其中所选文本也是替换文本的一部分。

我认为在这种情况下,宏是一个更好的工具。

要创建宏,首先选择要在静态强制转换中包装的第一段文本。例如,选择return_int_func()。 (对于每个步骤,我将显示缓冲区的样子。)

  1. 准备好后,按 qq 开始录制到注册q,然后按 c

    float fv = |;
    
  2. 键入包装文本的左侧部分static_cast<float>(

    float fv = static_cast<float>(|;
    
  3. CTRL-R " (Control-R后跟"):这将重新插入原始文本。

    float fv = static_cast<float>(return_int_func()|;
    
  4. 键入)以完成更改,然后退出以退出插入模式。

    float fv = static_cast<float>(return_int_func()▉;
    
  5. 最后,按 q 停止录制。

  6. 此时您已进行了第一次更改,并将其记录为注册q中的宏。

    对于所有剩余的更改,只需选择obj->load_int_field("name")等目标,然后按 @q 重复更改。

    查找:help 10.1以获取有关宏的更多信息。

答案 1 :(得分:1)

解决方案几乎太容易了!在这里。

:s/\%V.*\%V./static_cast<float>(&)/

这实际上与:help中的示例几乎相同。我们可以忽略这一点,我们应该在早上第一件事:h /\%V抬起头来......

\%V是零宽度原子,匹配在可视模式下选择的内容。它可以在Visual区域的开头匹配。 .*然后尽可能多地匹配(贪婪);它的贪婪是由最后的\%V.控制的,它要求匹配的最后一个字符也位于可视区域内。


提示:如果您需要在多行上多次进行此更改,请定义以下映射(更好的是:永久地将它们放入vimrc中)。

nnoremap & :&&<CR>
xnoremap & :&&<CR>

然后,您可以通过简单地选择一些内容重复上面显示的替换,然后按&来执行替换。

答案 2 :(得分:0)

\%V设施实际上并非用于对所选文本进行整体操作;更多用于搜索该文本。

假设您将把它放入一个函数或者将它映射到一个组合键,这里有一个替代方法可以满足您的需求:

:exec 'normal! gv"adistatic_cast<float>('|exec 'normal! "apa)' 

请注意,这将使用您的a缓冲区,因此,如果您想使用其他缓冲区,则可以使用"a更改"x的两个实例,其中x为你想要使用的缓冲区。

基本上,这将以编程方式抽取所选文本,插入static_cast<float>(,粘贴所选文本,然后插入)

答案 3 :(得分:0)

你可以尝试

:%s/float fv =(.*)$/float fv = static_cast<float>(\1)/g

答案 4 :(得分:0)

如果我理解正确,您只想对所选文本进行文本替换。这不是那么容易做到的,至少没有:s命令那么容易。因为,您的视觉选择可以是单行,可以跨越多行,也可以是明智的,逐行的,块状的。

但可以使用此功能完成:

function! SubVisualText(pat, repl,flag)
    try
        let v_save = @v
        normal! gv"vy
        let s = @v
        let s = substitute(s, a:pat, a:repl,a:flag) 
        call setreg('v',s,visualmode())
        normal! gv"vp
    finally
        let @v = v_save
    endtry
endfunction 

你通过以下方式使用它:

  • 获取功能
  • 直观地选择区域(可以vVCtrl-V完成)
  • :<ctrl-u>call SubVisualText(pattern, replacement, flag)<Enter>

<ctrl-u>用于删除前导范围,因为该函数不需要范围。

当你运行它时,它看起来像:(我刚用Ctrl-V选择测试)

enter image description here