在vim中,我可以访问bash环境变量,如$PWD和$PATH。我也想知道如何在vim中访问我的临时shell变量。
例如,假设我在终端中,并定义了一个变量foo="bar"
。然后我输入vim,并尝试使用以下命令:!echo $foo
访问此变量,但它无法识别此变量。根据我的理解,每次调用bash命令时,vim都会启动一个新的shell,然后立即关闭它。有没有办法在vim中使用与我的局部变量foo
定义的shell相同的shell?
不,您不能从父shell派生的子进程与父shell交互(如果没有该shell的积极参与,这在当前场景中是不合理/实际可用的),但您可以导出变量,使其可用于子进程中启动的新shell。
运行
set -a
将使以后定义的任何变量自动导出到环境中,即使没有显式的export
命令。
由于(与Csystem()
函数不同)vim的system()
接受SHELL
环境变量,如果SHELL=/bin/bash
(或:set shell=/bin/bash
已在vim中运行),您也可以从vim调用导出的函数。也就是说,如果您定义函数并将其导出如下:
foo() { echo "bar"; }
export -f foo
然后您可以从vim内部用CCD_ 10调用它。
然而,即便如此,它还是在一个新的、瞬态的shell实例中运行,而不是在原始父进程中运行。
说明
环境变量和shell变量是两个完全不同的概念,但当我们在bash中以类似的方式操作它们时,很容易混淆。
-
无论何时(通过fork)创建进程,它都可能包括一个环境,该环境由其父进程在fork时给定。然后,子进程可以访问和修改其内容。作为用户,如何做到这一点取决于程序:
- 在vim中,您可以访问这样的环境变量:
:echo $foo
- 在bash中,您可以这样访问它:
$ echo "$foo"
- 在大多数编程语言中,您可以使用与该语言的其他部分一致的语法来访问它,例如ruby中的
ENV['foo']
- 在vim中,您可以访问这样的环境变量:
-
另一方面,程序可以为任何内部用途分配内存,但值得注意的是,它经常定义和使用变量。再一次,这取决于程序:
- 在vim中,您可以使用:let命令来分配一个内部变量
- 在bash中,您可以用
$ foo='bar'
分配一个变量,然后用$ echo "$foo"
读取它 - 在大多数编程语言中,都有
foo='bar'
语法的变体,有时还有类型声明等
正如您所看到的,bash使用相同的语法来读取环境变量和它自己的一个私有变量,这可能会导致一些混乱。
当您从bash shell执行vim
时,环境会从父进程(bash)复制到子进程(vim),但bash的私有内存(包括您可能定义的变量)不会。
因此,从子进程访问它们将需要父进程和子进程之间的某种进程间通信机制。虽然在技术上可行,但这个选项在bash和vim中都没有实现。
解决方案
为了让您的变量能够从vim(或任何分叉进程)访问,您需要它出现在您的vim进程的环境中。
有几种选择:
$ export foo='bar'
:这将标记您的变量,以便导出到随后执行的命令的环境中。在大多数情况下,这就是你想要的$ foo='bar' vim
:这会将您的变量添加到Thisvim命令的环境中。对于故障排除或单行程序非常有用$ set -a
:正如您在bash手册页中看到的,它标记了每个后续定义,以便导出到后续命令的环境中。它本质上等同于用export
为每个后续定义做准备
进一步
-
问题使用
:!echo $foo
语法来显示foo
的值,这是另一个用例。这里的!
实际上是一个转义序列,它允许您从vim执行shell命令。但是,vim不能在父shell(在中执行
vim
命令的shell)中执行任何内容,因此它在子进程中创建一个新的bash shell,在其中执行echo
,并显示结果。在目前的情况下,结果基本相同,但在其他情况下很容易产生误导,因此了解这里发生的事情很重要。
-
还有另一种vim语法,使用
expand
,可以查找变量::echo expand("$foo")
然而,它的工作方式完全不同。
如果不存在名为
foo
的内部变量,vim将调用一个shell来查找它(类似于!
的操作)。此选项方式比环境查找慢,不建议用于大多数用例。
如果您想在:substitute
命令上使用shell中的值,实际上有一种方法可以做到这一点。
我不知道它是否能满足你的需求,但我们开始吧。
假设我们想用你的PWD
:代替Mydir
:s/Mydir/=expand($PWD)/g