在 Vim 中,搜索对于换行符,请将其输入为\n
,但替换字符串中的换行符必须输入为\r
。我理解这种行为的原因,但就我的目的而言,我发现这很烦人。我希望能够\n
在搜索模式和替换字符串中使用 来表示(本质上)相同的意思:具体来说,在搜索模式中它应该匹配换行符,而在替换字符串中它应该插入换行符。
有没有办法实现这种行为?我认为简单的重新映射不会起作用,因为需要解析替换命令才能确定它\n
是搜索模式的一部分还是替换字符串。
答案1
您必须连接到命令行;无论是通过 执行时<CR>
,还是在输入 时立即执行\n
。使用:help c_CTRL-\_e
,您可以评估函数并修改命令行。这是一个您可以在此基础上进行构建和改进的演示(现在对替换的检查非常简单):
cnoremap n <C-\>eTranslateBackslashN()<CR>
function! TranslateBackslashN()
if getcmdtype() ==# ':' && getcmdline() =~# 's/.*/.*\\$' " Improve this!
return getcmdline() . 'r'
endif
return getcmdline() . 'n'
endfunction
答案2
正如 Ingo Karkat 所写,可以使用 找到解决方案c_CTRL-\_e
。这是我使用的版本,除了正则表达式模式外,它与原始解决方案相同。(因为这实际上只是 Ingo Karkat 的答案,略有改进由 Ingo Karkat 建议,我不认为它实际上值得有自己的答案,但我想我被否决了:http://chat.stackexchange.com/transcript/message/15021397#15021397)
function! TranslateBackslashN()
if getcmdtype() ==# ':' && getcmdline() =~#
\ '[%>]s\([um]\w*\)\?\(.\).\{-}\(\\\)\@<!\2.*\\$'
return getcmdline() . 'r'
endif
return getcmdline() . 'n'
endfunction
cnoremap n <C-\>eTranslateBackslashN()<CR>
正则表达式模式的解释:
[%>]s
确保替换仅s
在范围之后立即发生\([um]\w*\)\?
匹配s
命令的变体,例如smagic
。\(.\)
将是第一个非单词字符,因为所有单词字符都已被\w
可选组所吃掉。请注意,这是组2
。这是分隔符,通常为/
。请注意_
,是单词字符,也是有效分隔符,因此如果以_
这种方式使用,模式将无法正常工作。_
不过,我从来没有用过 用作分隔符,所以我不会担心它。同样,有些字符不是单词字符,但不应该用作分隔符,但我在这里并不担心,因为在那种情况下命令无论如何都会失败。我想\W
在这里使用,但由于某种原因,我在测试它时它没有起作用。.\{-}
应该匹配模式(\{-}
就像 Perl 的一样*?
)。\(\\\)\@<!\2
匹配下一个前面没有反斜杠的分隔符。Perl 中的等价字符是(?<!\\)\2
。.*
匹配迄今为止替换字符串中的所有内容。\\$
仅当目前的命令以反斜杠结尾时才匹配。