在vim中,我可以访问我的bash环境变量,例如$PWD和$PATH。我想知道如何在vim中访问临时shell变量。
例如,假设我在终端中定义一个变量foo="bar"
。然后进入vim并尝试使用以下命令:!echo $foo
访问此变量,但它无法识别此变量。据我所知,每次调用bash命令时,vim都会启动一个新的shell,然后立即关闭它。是否有一种方法可以在vim中使用与定义foo
的本地变量相同的shell?
在vim中,我可以访问我的bash环境变量,例如$PWD和$PATH。我想知道如何在vim中访问临时shell变量。
例如,假设我在终端中定义一个变量foo="bar"
。然后进入vim并尝试使用以下命令:!echo $foo
访问此变量,但它无法识别此变量。据我所知,每次调用bash命令时,vim都会启动一个新的shell,然后立即关闭它。是否有一种方法可以在vim中使用与定义foo
的本地变量相同的shell?
set -a
...将使得任何定义的变量自动导出到环境中,即使没有显式的export
命令。
与C语言的system()
函数不同,vim的system()
函数会遵循SHELL
环境变量。如果SHELL=/bin/bash
(或在vim中运行了:set shell=/bin/bash
),您还可以从vim中调用已导出的函数。也就是说,如果您按照以下方式定义并导出函数:
foo() { echo "bar"; }
export -f foo
如果你定义了foo函数,那么你可以在vim内部使用!foo
来调用。
即使如此,这仍然在一个新的、短暂的shell实例中运行,而不是原始的父进程。
环境变量和shell变量是两个完全不同的概念,但在bash中以类似的方式操作它们,很容易混淆。
每当创建一个进程(通过fork),它可能包含一个环境,在fork时由其父进程给出。然后子进程可以访问和修改其内容。作为用户如何完成这个过程取决于程序:
:echo $foo
$ echo "$foo"
ENV['foo']
另一方面,程序可能会为任何内部使用分配内存,但特别是它经常定义和使用变量。再次,这取决于程序:
$ foo='bar'
分配变量,然后使用$ echo "$foo"
读取它foo='bar'
语法的变化,有时带有类型声明等正如您所看到的,bash 使用相同的语法来读取环境变量和其自己的私有变量,这可能会导致一些混淆。
当您从bash shell执行vim
时,环境从父进程(bash)复制到子进程(vim),但是bash的私有内存(包括您可能定义的变量)不会被复制。
因此,从子进程访问它们需要一些进程间通信机制,在父进程和子进程之间。虽然在技术上可行,但bash和vim没有实现此选项。
为了使您的变量可以从vim(或任何分叉进程)中访问,您需要将其存在于vim进程的环境中。
有几个选项:
$ export foo='bar'
:这将标记您的变量以供随后执行的命令环境导出。在大多数情况下,这是您想要的。$ foo='bar' vim
:这将添加您的变量到此 vim 命令的环境中。非常适用于故障排除或单行命令。$ set -a
:从bash manpage中可以看出,这将标记每个后续定义以便导出到后续命令的环境中。它本质上相当于在每个后续定义之前加上export
。问题使用了:!echo $foo
语法显示foo
的值,这是另一个用例。这里的!
实际上是一个转义序列,允许您从vim中执行一个shell命令。
但是,vim无法在父shell(您执行vim
命令的那个)中执行任何操作,因此它会在子进程中创建一个新的bash shell,在其中执行echo
并显示结果。
在当前情况下,结果大多相同,但在其他情况下可能很容易产生误导,因此了解此处发生的情况非常重要。
有另一种vim语法,使用expand
,允许查找变量::echo expand("$foo")
它的工作方式完全不同。
如果不存在名为foo
的内部变量,则vim将调用shell来查找它(类似于!
会做的事情)。
这个选项比环境查找慢得多,对于大多数用例而言不建议使用。
:e ^R=expand($myprojectdir)
的意思是,当按下<c-r>时,您可以交互地展开变量以在ex中使用。 - MacMartin:e ^R=expand($myprojectdir)
的意思是,当按下<c-r>时,你可以交互地展开变量以在ex中使用。 - undefined:substitute
命令中使用来自您的shell的值,实际上有一种方法可以做到。PWD
替换Mydir
::s/Mydir/\=expand($PWD)/g