在vim中,我可以访问bash环境变量,例如$ PWD和$ PATH。我也想知道如何在vim中访问我的临时shell变量。
例如,假设我在终端中并定义了一个变量foo="bar"。然后,我输入vim并尝试使用以下命令访问此变量:!echo $foo,但它无法识别该变量。据我了解,每次调用bash命令时,vim都会启动一个新的shell,然后立即关闭它。有没有办法在vim中使用与foo定义本地变量相同的shell ?
不,您不能从其产生的子流程中与父Shell进行交互(没有该Shell的积极参与,这在当前情况下是不合理/实际的)–但您可以导出变量以使它们可访问在子进程中启动了新的shell。
跑步
set -a
Run Code Online (Sandbox Code Playgroud)
...将使以后定义的任何变量都自动导出到环境中,即使没有显式export命令也是如此。
由于(不同于C system()函数)vim会system()使用SHELL环境变量,因此SHELL=/bin/bash(如果:set shell=/bin/bash已在vim中运行),也可以从vim调用导出的函数。也就是说,如果您定义函数并按如下所示导出它:
foo() { echo "bar"; }
export -f foo
Run Code Online (Sandbox Code Playgroud)
...然后您可以!foo从vim内部调用它。
但是,即使这样,它仍在新的临时shell实例中运行,而不是原始父进程。
环境变量和 shell 变量是两个完全不同的概念,但当我们在 bash 中以类似的方式操作它们时,很容易混淆。
每当创建一个进程(通过 fork)时,它都可能包含一个由其父进程在 fork 时给出的环境。然后子进程可以访问和修改其内容。用户如何完成此操作取决于程序:
:echo $foo$ echo "$foo"ENV['foo']在 ruby 中另一方面,程序可以分配内存供任何内部使用,但值得注意的是,它经常定义和使用变量。再次强调,这取决于程序:
$ 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 手册页中看到的,这标记了导出到后续命令环境的每个后续定义。它本质上相当于在每个后续定义前面加上export。该问题使用:!echo $foo语法来显示 的值foo,这是另一个用例。这里!实际上是一个转义序列,允许您从 vim 执行 shell 命令。
但是,vim 无法在父 shell(执行命令的那个 shell vim)中执行任何操作,因此它会在子进程中创建一个新的 bash shell,echo在其中执行并显示结果。
在当前情况下,结果基本相同,但在其他情况下很容易产生误导,因此了解这里发生的情况很重要。
还有另一种 vim 语法using expand,它允许人们查找变量::echo expand("$foo")
然而它的工作原理完全不同。
如果不foo存在名为 name 的内部变量,vim 将调用 shell 来查找它(类似于!执行的操作)。
此选项比环境查找慢得多,并且不建议在大多数用例中使用。