来自帮助:help backtick-expansion

On Unix and a few other systems you can also use backticks for the file name
argument, for example:
    :next `find . -name ver\*.c -print`
    :view `ls -t *.patch  \| head -n1`
The backslashes before the star are required to prevent the shell from
expanding "ver*.c" prior to execution of the find program.  The backslash
before the shell pipe symbol "|" prevents Vim from parsing it as command
termination.


如果键入从帮助中获取的命令,则会出现错误:

:next `find . -name ver\*.c -print
E79: Cannot expand wildcards  


为什么帮助中的示例使用两个反斜杠而不是一个反斜杠,为什么它不起作用?

以下工作:



如果我在find程序之前删除了两个反斜线之一,以防止恒星被壳扩展,则该反斜线之一:的反斜杠并在模式ver*.c周围加上单引号:并且您不希望外壳程序在命令前将其扩展,在其前面加一个反斜杠或在模式周围加上单引号。

但是帮助给出了另一个示例:

:next `find . -name ver\*.c -print`


此命令无需任何修改即可工作,不需要单引号,不需要反斜杠。
我想之所以起作用,是因为ls命令(与-name命令的find参数相反)接受多个文件参数,并且看到shell扩展*.patch没问题。

现在,假设我要查找.conf文件夹中所有扩展名为/etc的文件,并将find的输出通过管道传输到grep,以仅获取包含字符串input的匹配项。在shell中的任何工作目录中,我都将输入:

:next `find . -name 'ver*.c' -print`


它会起作用。

在vim中,我将键入相同的命令在其周围加上反引号,并在管道符号前面加一个反斜杠以防止vim将其解释为命令终止: />
现在,如果我输入相同的命令而不使用管道和grep input,则会出现错误:

:view `ls -t *.patch  \| head -n1`


即使我用单引号保护了星号,在这种情况下为什么还会出现错误?
为什么现在出现错误,而不仅仅是在管道和grep input之前出现错误?尝试理解,我想出了一个更简单的命令:

find /etc -name '*.conf' | grep input


它将在工作目录中查找所有扩展名为.conf的文件。该命令在外壳中有效。

要在vim中对其进行测试,我键入了::next `find . -name '*.conf'`
它有效。
在这种情况下,点代表显示的当前工作目录通过Ex命令:pwd,这是我的主目录/home/username,因为我从中启动了vim会话。

为什么当我要求在当前工作目录中进行搜索时它为什么起作用,而当我要求在诸如/etc这样的任意文件夹中进行搜索时却不起作用?

现在,如果我使用vim Ex命令/home/username将工作目录从/etc更改为:cd /etc,然后重试与以前相同的命令,则会再次出错:

:next `find /etc -name '*.conf' \| grep input`


为什么在我的主文件夹中时,相同的命令起作用,而在/etc中却不起作用?

我敢肯定有一些逻辑,但我找不到。

用任意shell命令(包含星号,管道,在任何工作目录中的任何目录中搜索)填充arglist的一般正确语法是什么?我使用的是vim版本7.4.942,而zsh是我的默认shell。
我使用最少的bash和zsh初始化(vim -u NORC -N)测试了这些命令。

我需要配置vim调用bash而不是zsh吗?

评论

我想知道您是否尝试使用所有作为参数传递的文件来启动vim?我的意思是这样的:vim $(find。-name ver * .c)

@VladGURDIGA我刚刚尝试过,它们都可以从shell中正常工作:vim $ {find。-name ver \ *。c -print),vim $ {ls -t * .patch | head -n1),vim $ (查找/ etc -name'* .conf'| grep输入),vim $(查找/ etc -name'* .conf'),vim $(查找。-name'* .conf')

@VladGURDIGA但是我想知道如何填充arglist而不退出当前会话,因为我通常只有一个会话。我也可以在外壳中四处走动,搜索一组文件,然后将它们发送到Vim服务器(使用参数--remote,请参见:vi.stackexchange.com/a/5618/4939),但我很好奇知道如何直接从当前会话中进行操作。如果这不可能,那很好,但是在阅读了帮助之后,看来可以完成。如果是这样,我想了解为什么vim对类似命令的反应如此不同。

嘿,似乎在第一个示例命令中,您缺少结束符。 ;)除此之外,我想帮助中的示例使用两个反斜杠而不是一个反斜杠来防止外壳扩展,如此处所述:unix.stackexchange.com/q/104260/23669。

对于find / etc -name'* .conf'无效的情况,我认为该命令中出现了一些有趣的名称,这可能是它通过grep传递时起作用的原因。

#1 楼

我仍然不知道如何使用反引号扩展来使用任意的shell命令填充arglist,但是我找到了一种解决方法。

来自:help `=: br />
我们可以将shell命令发送到Vim函数systemlist()并使用表达式寄存器=扩展结果表达式,如下所示:

You can have the backticks expanded as a Vim expression, instead of as an
external command, by putting an equal sign right after the first backtick,
e.g.:
    :e `=tempname()`
The expression can contain just about anything, thus this can also be used to
avoid the special meaning of '"', '|', '%' and '#'.  However, 'wildignore'
does apply like to other wildcards.


保存一些击键,我在vimrc中定义了以下Ex命令(:PA表示“填充Arglist”): >
:args `shell command`


到目前为止,它可以像预期的那样工作,并且可以像在shell中一样键入命令(例如,无需转义管道)。比直接反引号扩展更加一致和可靠。