How can I escape the % and # characters in a Vim command?
I'm using Ack (https://github.com/mileszs/ack.vim) with the --literal
flag to search through projects in Vim. I noticed that whenever I search for a string with the %
or #
characters, the search doesn't match things as I'd expect it to. I did some research and found that it's because Vim will expand these characters in commands (%
is the current file and #
to something else, not sure what).
This is pretty annoying behavior when performing a search, considering these symbols come up pretty often in code. Is there a way to escape them, preferably automatically, so that the search works as expected? My current mapping is: nnoremap <leader>al :Ack --literal<space>
.
Example
Say I have a selector #body
in a CSS file someplace and I want to find it. These are the things I've tried (that haven't worked):
:Ack --literal #body
:Ack --literal \#body
:Ack --literal "#body"
:Ack --literal "\#body"
Any ideas why escaping wouldn't work as usual here, or what this is even searching fo开发者_如何转开发r? I haven't had these examples match anything.
Solution
I've gotten it to work by double-escaping the characters. For example, :Ack --literal "\\#body"
will show :ack -H --nocolor --nogroup --column --literal "#body"
in the statusline of the result window and bring up the expected results. The quotes seem to be required as well.
You just prefix them with a backslash
:!echo %
outputs the current buffer's filename
:!echo \%
prints a solitary '%' character
Apparently you have to escape multiple times as mentioned in an ack.vim issue:
:Ack \\\#foo
I have one addition to @sehe's answer: when you do !...
or system('...')
vim does not process ...
by itself, but calls shell, like this: {shell} {shellcmdflag} {shellxquote}...{shellxquote}
. For ack call this will be something like ["/bin/bash", "-c", "ack -H --nocolor --nogroup --literal #body"]
, so bash will ignore everything after --literal
because #
is a comment character. It won't do so for '#body'
because no comments are possible inside a quoted string.
It is a bug in ack.vim, somehow the ack program isn't even being called when you do :Ack --literal \#body
However, I used
`strace -f -o-e trace=process gvim | tee /tmp/log`
And it seems that doing :Ack --literal '\#body'
(mind the extra quotes) does work as expected:
[pid 3833] execve("/usr/bin/ack", ["ack", "-H", "--nocolor", "--nogroup", "--literal", "#body"], [/* 25 vars */] <unfinished ...>
I haven't really tested it...
精彩评论