如何轻松转义命令行过滤器

时间:2018-04-02 21:46:58

标签: vim escaping

我已经看过有关在Vim中执行

类型管道的讨论
:%! cmd1 | cmd2 | ...

它也适用于:w

:.w !cat | cat

它适用于:r

:r !echo hello | cat
:r !ls | grep .mp4

但是第二次我尝试了一些更雄心勃勃的事情,比如,awk,它停止了工作:

:r !ls | awk '{printf "\"%s\"\n", $0}'
E499: Empty file name for '%' or '#', only works with ":p:h"

我已尝试了几十种语法变体来使其工作,包括在!之后使用()包围整个命令行,但它只是拒绝处理有关空文件的内容名称。这是导致我在Google上搜索并找出管道是否真的在Vim中工作的原因。事实是,它不是awk的问题。以下是在bash shell上使用相同的命令行会发生什么:

$ ls | awk '{printf "\"%s\"\n", $0}'
"somefile1"
"somefile2"
"somefile3"
"somefile4"

它也适用于sh(或我系统上的dash)。

如何让vim停止误解我的输入?实际上,我只是想出了解决这个问题的具体问题的解决方案。您必须转义%,因此它不会将其解释为已打开文件的名称。

:r !ls | awk '{printf "\"\%s\"\n", $0}'
                         ^

然而,这仍然是令人讨厌的行为(让IMO感到困惑,Vim在%的逃脱看起来就像是awk的逃脱;人们怎么会知道这样做会赢得' t导致awk按字面输出"%s"\n?这对我来说是一个疯狂的猜测。

我想知道是否有一种完全逃避filter!之后的部分)的方式,这样我就不必慢慢解析我的意思为Vim编写和特殊情况。过度复杂的转义很快就变得难以理解,而且在元编程方面是我的烦恼之一。

当然必须有一种简单的方法来告诉Vim忽略像%等字符,并按原样将它们传递给shell,以便我可以测试我的命令shell并将它们复制/粘贴到Vim中,而不必担心手动转义特定字符,因为我可以想象这很容易成为屁股的巨大痛苦。

实际上,这有点像XY问题。不过,我必须在不同的问题上发布原始问题,因为Y问题非常有趣,我想知道。我会在评论中发布X问题的链接。

1 个答案:

答案 0 :(得分:1)

您使用shellescape()的尝试即将结束。您所缺少的:

  • 对于:!(和:r !),您需要将1标志的{special}传递给它。
  • 您只能使用单个转义的命令行参数,而不是整个命令行。由于您在最后一个(awk脚本)参数中仅包含关键字符,因此我们仅在此处需要它:
:exe 'r ! ls | awk ' . shellescape('{printf "\"%s\"\n", $0}', 1)