1

在以下代码中:

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...替换为and 这根本不是我想要的。然后我尝试了这个:

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

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

4

5 回答 5

1

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

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

要创建宏,首先选择要在静态转换中换行的第一段文本。例如,选择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. 键入)以完成更改,然后 Escape 退出插入模式。

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

此时您已经进行了第一次更改,并将其作为宏记录在 register 中q

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

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

于 2013-10-23T10:51:44.993 回答
1

解决方案几乎太简单了!这里是。

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

这实际上与:help. 我们可以摆脱这一点,我们都应该:h /\%V在早上的第一件事就是抬头......

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


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

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

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

于 2013-10-23T13:05:30.537 回答
0

\%V工具实际上不适用于对整个选定文本进行操作;更多用于在该文本中进行搜索。

假设您要将其放入一个函数中,或者可能将其映射到一个组合键,这是一种替代方法,可以满足您的需求:

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

请注意,这将使用您的a缓冲区,因此如果您想使用另一个缓冲区,您可以更改"awith的两个实例,您希望使用的缓​​冲区"x在哪里。x

基本上,这将以编程方式拉出选定的文本,插入static_cast<float>(,粘贴选定的文本,然后插入)

于 2013-10-23T02:19:58.203 回答
0

你可以试试

:%s/float fv =(.*)$/float fv = static_cast<float>(\1)/g
于 2013-10-23T02:55:07.930 回答
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 

您通过以下方式使用它:

  • 源函数
  • 视觉选择区域(可以通过v,VCtrl-V
  • :<ctrl-u>call SubVisualText(pattern, replacement, flag)<Enter>

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

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

在此处输入图像描述

于 2013-10-23T09:54:17.200 回答