哪些Vim命令可用于引用/取消引用单词?


204

如何在Vim中快速引用/取消引用单词并更改引用(例如,从'")?我了解surround.vim插件,但我想用刚Vim的。


解决方案实际上取决于上下文。您是要只一行执行,还是要在整个文件中执行,还是只针对单个带引号的字符串执行此操作?
Lucas Oman 2010年

对于一行中的单个单词或所有单词。例如,将粘贴的单词转换为字符串文字时。
尤金·雅玛什

Answers:


251

Surround.vim将是您最简单的答案。如果您真的不喜欢使用它,那么这里有一些您可以做的例子。不一定是最高效的,但这就是为什么Surround.vim被编写的原因。

  • 用单引号引用一个单词
    ciw'Ctrl+r"'
    • ciw -删除光标所在的单词,并以插入模式结束。
    • ' -添加第一个报价。
    • Ctrl+r"-插入"寄存器的内容,也就是最后一次取消/删除。
    • ' -添加结束语。

  • 取消引用单引号中包含的单词
    di'hPl2x
    • di' -删除单引号引起的单词。
    • hP -将光标向左移动一个位置(在引号的顶部),然后将刚删除的文本放在引号之前。
    • l -将光标向右移动一个位置(在引号上方)。
    • 2x -删除两个引号。

  • 将单引号更改为双引号
    va':s/\%V'\%V/"/g
    • va' -直观地选择带引号的单词和引号。
    • :s/ -开始更换。
    • \%V'\%V -仅匹配视觉选择区域内的单引号。
    • /"/g -用双引号将它们全部替换。

1
这些对我来说很好。只是谷歌搜索,也可以使用Ctrl + op在插入模式下粘贴。
尤金·雅玛什

1
与记录模式(q)结合使用时,可像快速工作的魅力一样工作。
主教

为什么ciw而不仅仅是cw?我发现第一个令人困惑,第二个很好。
Big McLargeHuge 2015年

17
ciw无论您的光标在单词中的哪个位置,@ Koveras都可以工作。 cw仅在光标位于单词开头时才有效。请参阅:help iw
jamessan 2015年

10
劫持最高答案可以得到一个不错的小窍门:如果您有多个单词要替换双引号中的单引号,您可能会注意到@jamessan的第一个解决方案不适用于该.命令。要使其正常工作,请使用ciw' Ctrl+r Ctrl+p"。然后.将按照您希望的方式执行以下单词:与其记住寄存器的内容,不如记住寄存器现在要的内容(有点难以解释,但是如果您同时尝试,它将变得很明显) :
autra 2015年

182

用单引号引用一个单词

ciw'Ctrl+r"'

这样对我来说更容易

ciw '' Esc P

8
不幸的是,这似乎不允许这样做。(重复)。
威尔·摩尔三世

2
我更喜欢这样做,因为我可以在带有vim模式的终端机/回复中使用它,因为Ctrl + r通常已经用于反向历史记录搜索。
09分-krock

3
@wilmoore将以上内容记录为宏,然后重播。
Christopher

30

这里有一些映射可以帮助您:

:nnoremap <Leader>q" ciw""<Esc>P
:nnoremap <Leader>q' ciw''<Esc>P
:nnoremap <Leader>qd daW"=substitute(@@,"'\\\|\"","","g")<CR>P

如果您尚未更改mapleader变量,请使用\q" \q'或激活映射\qd。它们在光标下方的单词周围添加双引号,在光标下方的单词周围添加单引号,并分别删除光标下方的单词周围的所有引号。


真棒的想法!我最终添加map <Leader>' gewi'<Esc>A'<Esc>.vimrc文件中,以从当前位置到行尾插入单引号注释;这在将一些MSDOS脚本转换为bash时帮助了我。
ILMostro_7 2014年

@Geoff,它对单引号有效。但是对于双引号,它会在单词的
前面

@RameshVel您可能有一些自己的宏会影响映射的右侧。我将映射命令更新为nnoremap,以便不扩展其他映射。我还改进了映射。当光标位于一行的第一个单词时,前一个有问题。
杰夫·里迪

这也可以很容易地适用于可视模式,以用引号将所选内容括起来,例如:vnoremap <leader>q c""<esc>P
多米尼克

27

除了其他命令之外,这还将所有单词用双引号引起来(根据您的注释)

:s/\(\S\+\)/"\1"/

或者如果您想减少反斜杠的数量,可以\v在模式的开头放置一个(非常神奇的)修饰符

:s/\v(\S+)/"\1"/

我复制的文字中也有逗号,所以我改成了:s/\v([a-Z]+)/"\1"/g
tsukimi

22

宏的方式!

  1. qq记录到q寄存器中(我们使用“ q”作为记住“引号”的快捷方式)。

  2. shift+ b将光标移到当前单词的前面

  3. i类型'(单引号)

  4. esc然后按e移动到单词的末尾

  5. 按,a然后再按'一次,用引号将单词引起来。

  6. esc进入普通模式。

  7. 最后按q将其记录到q寄存器中。

如何使用

  1. 将光标移到所需的单词。
  2. @q以用引号将单词引起来。
  3. 新闻@@,如果你想重复它变成另一个字。

你可以改变 step 4用任何喜欢的内容 {一行,一个单词,直到找到某个字符,等等}。

使录制的宏持久化

  1. 打开.vimrc
  2. 转到文件末尾
  3. 更改为插入模式。输入以下内容使其持久化:
让@ q =' ctrl+ r ctrl+ rq'
  1. 保存并退出

  2. 打开文件,输入一些单词

  3. 现在按 @q

如果操作正确,您的话中应该会出现神奇的事物。

您可以对自己喜欢的其他宏执行此步骤。


3
不得不说我喜欢这个解决方案。不需要Surround.vim,也可以轻松调用和创建宏。也可以轻松用于您需要的其他任何内容(例如,对我来说,将当前单词引至行尾,非常适合ansible)。要显示该宏,请执行以下操作:“ qp。要保存该宏,请转到.vimrc并执行:let @q ='macro contents'(仅出于完整性考虑)
th3penguinwhisperer

我很喜欢这个 您也可以嵌套这些宏。因此,您可以记录在寄存器j中@q w,然后可以n使用with使用引号将后面的单词引起来n@j
隐藏用户名

1
我添加了一些使宏持久化的步骤。
Brain90 '19

1
Pedantic,但是,单词和单词在Vim中是不同的。Shift + b = B,因此理想情况下,应将步骤2更改为“ ...当前字词的开头”。但是,如果您要说的是单词开头,则无需使用Shift。
Ambareesh

谢谢你的意思。我故意使用shift + b处理WORD。该宏应以字或字[0]的形式运行。实际上,第3步也应更改为shift + e。[0] stackoverflow.com/a/14390568/341959
Brain90

18

以单引号引起来(例如)ciw'<C-r>"'<esc>有效,但重复将不起作用。尝试:

ciw'<C-r><C-o>"'<esc>

这会将默认寄存器的内容“按字面意义”放置。现在,您可以按.任意单词以将其用引号引起来。要了解更多信息,请:h[elp] i_ctrl-r访问::h text-objects

资料来源:http : //vimcasts.org/episodes/pasting-from-insert-mode/


2
很棒的提示!如果有人想对此进行映射,则正确的符号为ciw'<C-R><C-O>"'<Esc>
2013年

<Cr>“的确切功能是什么?
CodeCrack 2015年

@CodeCrack是CTRL-R。CTRL-R将寄存器的内容插入到光标处,并保持在插入模式。
Erwin Rooijakkers

正如您所提到的,这是可重复的,但是当存储在宏中时,重复使用宏.将重写最后一次实际调用的内容。
Sbu

7

对于VSCodeVim的用户,您可以

vwS"

  • 您可以更换 "用任何您想包装的东西。
  • 您可以w用任何其他选择运算符替换

2
这在MacVIM上对我也很有效,但是我不得不使用viwS'将单引号括起来的单词。到目前为止最简单的。
马特·格兰纳里

仅当您在单词开头时才有效。如果您想在单词中的任何位置进行操作,则可以执行以下操作:viwS"
geoyws

6

我不知道有任何内置的vim命令,但是如果您站在第一个'或'上,则可以使用r"f'r"从'更改为'和从' r'f"r'更改为'的方法。该命令r'将光标下的任何字符替换为',然后f"将您移至下一个“。


1
对我来说最直观的“手动”解决方案。如果您想更改更多的引号,则只需键入And 即可代替第二个替换命令('r"r),并转到下一个或上一个.引号,因为它们分别沿相同方向或相反方向重复了最后一个搜索。;,f/F/t/T
Endre双方2015年

5

添加报价

我开始在我的中使用此快速而肮脏的功能.vimrc

vnoremap q <esc>:call QuickWrap("'")<cr>
vnoremap Q <esc>:call QuickWrap('"')<cr>

function! QuickWrap(wrapper)
  let l:w = a:wrapper
  let l:inside_or_around = (&selection == 'exclusive') ? ('i') : ('a')
  normal `>
  execute "normal " . inside_or_around . escape(w, '\')
  normal `<
  execute "normal i" . escape(w, '\')
  normal `<
endfunction

因此,现在,我在视觉上选择想要的引号(通常通过viw-视觉上选择单词内),然后按Q双引号,或者按q单引号。

删除引号

vnoremap s <esc>:call StripWrap()<cr>

function! StripWrap()
  normal `>x`<x
endfunction

我使用vim-textobj-quotes,以便vim将引号视为文本对象。这意味着我可以做vaq(直观地选择引号包围。这寻找最近的报价,并在视觉上选择它们。(这是可选的,你可以这样做f"vww),然后我按s剥离从选择的报价。

更改报价

吻。我删除引号,然后添加引号。例如,要将单引号替换为双引号,我将执行以下步骤:1.删除单引号:vaqs,2.添加新的引号:vwQ



4

如果您使用vim插件https://github.com/tpope/vim-surround(或使用VSCode Vim插件,该插件已预先安装了vim-surround),它非常方便!

ysiw' // surround in word `'`

下降

ds' // drop surround `'`

更改

cs'" // change surround from `'` to `"`

它甚至适用于html标签!

cst<em> // change surround from current tag to `<em>`

查看github上的自述文件以获得更好的示例


2

以下是一些简单的映射,可用于引用和取消引用单词:

" 'quote' a word
nnoremap qw :silent! normal mpea'<Esc>bi'<Esc>`pl
" double "quote" a word
nnoremap qd :silent! normal mpea"<Esc>bi"<Esc>`pl
" remove quotes from a word
nnoremap wq :silent! normal mpeld bhd `ph<CR>

1
如果您可以详细说明答案,那么这对每个人都很好:如何添加映射,如何调用映射等。谢谢。
卡尔斯·阿尔科利亚

1
我要说的是引号,双引号和qw qd wq
取消

出于某种原因,双引号的,如“词””最后返回额外的报价。
janicebaratheon

@ShuaiWang也许您已经安装了自动配对或某些类似的扩展程序?删除该错误已为我修复。
Nephilim

2

VIM for vscode做到了这一点。如果您不使用vscode,它基于一个vim-surround

一些例子:

“ test”(光标位于引号内,键入cs”)结尾为“ test”

“ test”(光标位于引号内,输入类型为ds)以测试结束

光标位于引号内的“测试”键入cs“ t并输入123>以<123> test结尾

用光标在单词测试类型ysaw上进行测试),最后得到(test)


1

我在我的.vimrc中使用nnoremap

单引号:

nnoremap sq :silent! normal mpea'<Esc>bi'<Esc>`pl

要删除引号(也可以在双引号上使用):

nnoremap qs :silent! normal mpeld bhd `ph<CR>

要记住的规则:“ sq” =单引号。


0

这个怎么样?

 :%s/\'/"/g

2
此命令对整个文件起作用。我只需要更改一个单词。
尤金·雅玛什

4
如果不使用%,则除非您选择了整个文件,否则它将仅在当前行起作用
Emily 2010年

0

我写了一个脚本来做到这一点:

function! WrapSelect (front)
    "puts characters around the selected text.
    let l:front = a:front
    if (a:front == '[')
        let l:back = ']'
    elseif (a:front == '(')
        let l:back = ')'
    elseif (a:front == '{')
        let l:back = '}'
    elseif (a:front == '<')
        let l:back = '>'
    elseif (a:front =~ " ")
        let l:split = split(a:front)
        let l:back = l:split[1]
        let l:front = l:split[0]
    else
        let l:back = a:front
    endif
    "execute: concat all these strings. '.' means "concat without spaces"
    "norm means "run in normal mode and also be able to use \<C-x> characters"
    "gv means "get the previous visual selection back up"
    "c means "cut visual selection and go to insert mode"
    "\<C-R> means "insert the contents of a register. in this case, the
    "default register"
    execute 'norm! gvc' . l:front. "\<C-R>\""  . l:back
endfunction
vnoremap <C-l> :<C-u>call WrapSelect(input('Wrapping? Give both (space separated) or just the first one: '))<cr>

要使用该功能,只需突出显示某些内容,单击控件l,然后键入一个字符即可。如果它是函数知道的字符之一,它将提供正确的终止字符。如果不是,它将在两侧插入相同的字符。

Surround.vim不仅可以做到这一点,还可以满足我的需求。


-1

可视模式映射示例,用于在所选文本块周围添加单引号:

:vnoremap qq <Esc>`>a'<Esc>`<i'<Esc>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.