【问题标题】:How can I escape the % and # characters in a Vim command?如何转义 Vim 命令中的 % 和 # 字符?
【发布时间】:2014-04-08 06:36:33
【问题描述】:

我正在使用带有 --literal 标志的 Ack (https://github.com/mileszs/ack.vim) 在 Vim 中搜索项目。我注意到,每当我搜索带有 %# 字符的字符串时,搜索结果与我期望的不匹配。我做了一些研究,发现这是因为 Vim 会在命令中扩展这些字符(% 是当前文件,# 是其他文件,不确定是什么)。

在执行搜索时,考虑到这些符号在代码中经常出现,这是非常烦人的行为。有没有办法逃避它们,最好是自动的,以便搜索按预期工作?我目前的映射是:nnoremap <leader>al :Ack --literal<space>

示例

假设我在某处的 CSS 文件中有一个选择器 #body,我想找到它。这些是我尝试过的东西(没有奏效):

:Ack --literal #body
:Ack --literal \#body
:Ack --literal "#body"
:Ack --literal "\#body"

任何想法为什么转义在这里不能像往常一样工作,或者这甚至在搜索什么?我没有让这些例子匹配任何东西

解决方案

我已经通过双重转义字符来实现它。例如,:Ack --literal "\\#body" 将在结果窗口的状态行中显示:ack -H --nocolor --nogroup --column --literal "#body" 并显示预期的结果。引号似乎也是必需的。

【问题讨论】:

  • @Randy 这很有道理。谢谢!

标签: vim macvim ack


【解决方案1】:

你只需在它们前面加上一个反斜杠

:!echo %

输出当前缓冲区的文件名

:!echo \%

打印一个单独的 '%' 字符

【讨论】:

  • 感谢您的回答。您的示例按预期工作,但我已经更新了我的问题以包含一个此类转义不起作用的示例。关于为什么不/可以做什么的任何想法?
  • 这可能是 ack.vim 中的一个错误(它传递输入而不重新转义它)。我会联系作者/看看新版本是否修复它
  • 在 Vim versin 8.1 中,我必须使用像 \\# 这样的双斜线来转义 #,否则它不起作用。例如! echo \# 没有打印任何东西,但! echo \\# 打印了哈希字符。
  • @RajaRaviVarma 实际上并没有什么不同。这是因为# 是shell 注释字符。 !echo \# 实际上确实将 echo # 发送到 shell。您可以轻松地验证 echo # 实际上并未在 posix shell 中打印任何内容。于是,谜团解开了。添加第二个斜杠会将echo \# 发送到shell。我建议改为!echo '#'
  • 啊!谢谢@sehe,!echo '#' 没有按预期工作。但是! echo '\#' 做到了。
【解决方案2】:

显然你必须像an ack.vim issue中提到的那样多次转义:

:Ack \\\#foo

【讨论】:

    【解决方案3】:

    我对@sehe 的回答有一个补充:当您执行!...system('...') 时,vim 不会自行处理...,而是调用shell,如下所示:{shell} {shellcmdflag} {shellxquote}...{shellxquote}。对于 ack 调用,这将类似于 ["/bin/bash", "-c", "ack -H --nocolor --nogroup --literal #body"],因此 bash 将忽略 --literal 之后的所有内容,因为 # 是一个注释字符。 '#body' 不会这样做,因为在带引号的字符串中不可能有 cmets。

    【讨论】:

    • strace 显示 execve。这不会在任何时候调用任何 shell。它将直接调用具有精确的空分隔参数的二进制文件(即没有任何类型的扩展)
    • @sehe。是的当然。它是 shell 的 execve,而不是 vim 的。往回搜索,你会看到调用shell的execve。
    • @sehe。或者尝试解释为什么:!trap USR1 不显示任何错误而trap 可执行文件不存在(因为trap 只能作为shell 内置实现)。另见 'shell' 选项和朋友:如果 vim 不调用 shell,那么这些是干什么用的?
    • 你没有抓住重点。我已经展示了 (eventually) 使用正确的参数 here 运行 execve 的语法。在那个阶段,涉及多少层 shell 真的无关紧要。 ack 调用在当时被证明是正确的。
    • @sehe:重要的是:您已经解释了 what 是正确的语法,我解释了 为什么 它是正确的。如果您在某处发现不使用 ' 作为引号字符的外壳(如 cmd.exe),那么这将不是正确的语法,但我的回答仍然适用,并使 OP 能够找出是什么问题。你的答案不会。
    【解决方案4】:

    这是 ack.vim 中的一个错误,不知何故,当您执行 :Ack --literal \#body 时甚至没有调用 ack 程序

    但是,我用过

    `strace -f -o-e trace=process gvim | tee /tmp/log`
    

    看来:Ack --literal '\#body'(注意多余的引号)确实按预期工作:

    [pid  3833] execve("/usr/bin/ack", ["ack", "-H", "--nocolor", "--nogroup", "--literal", "#body"], [/* 25 vars */] <unfinished ...>
    

    我还没有真正测试过...

    【讨论】:

    • @John:你使用'\#body'这个语法有什么成功吗? execve 确实建议它应该工作(但我没有 ack)
    猜你喜欢
    • 2019-12-08
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-19
    相关资源
    最近更新 更多