在vim中访问本地shell变量

时间:2018-10-25 19:11:13

标签: bash vim

在vim中,我可以访问bash环境变量,例如$ PWD和$ PATH。我也想知道如何在vim中访问我的临时shell变量。

例如,假设我在终端中,并定义了一个变量foo="bar"。然后,我输入vim并尝试使用以下命令:!echo $foo访问此变量,但是它无法识别该变量。据我了解,每次调用bash命令时,vim都会启动一个新的shell,然后立即关闭它。是否可以在vim中使用与定义本地变量foo相同的shell?

3 个答案:

答案 0 :(得分:4)

不,您不能与它生成的子进程中的父Shell进行交互(没有该Shell的积极参与,这在当前情况下不可行/不可行),但是您可以导出变量,以使子进程中启动的新Shell可以访问它们。

运行

set -a

...即使没有明确的export命令,也会使以后定义的任何变量自动导出到环境中。


由于(不同于C system()函数),如果system()(或SHELL已在vim中运行),vim的SHELL=/bin/bash会优先使用:set shell=/bin/bash环境变量。 ,您也可以从vim调用导出的函数。也就是说,如果您定义函数并按如下所示导出它:

foo() { echo "bar"; }
export -f foo

...然后,您可以在vim内部用!foo调用它。

但是,即使这样,它仍在新的临时shell实例中运行,而不是在原始父进程中运行。

答案 1 :(得分:0)

说明

环境变量和外壳变量是两个完全不同的概念,但是当我们在bash中以相似的方式操作它们时,很容易感到困惑。

  • 无论何时(通过fork)创建进程,它都可能包含一个环境,该环境由其父级在fork时给出。然后,子进程可以访问和修改其内容。作为用户如何完成此操作取决于程序:

    • 在vim中,您可以access an environment variable像这样::echo $foo
    • 在bash中,您可以像这样访问它:$ echo "$foo"
    • 在大多数编程语言中,您可以使用与其他语言一致的语法来访问它,例如ruby中的ENV['foo']
  • 另一方面,程序可以为内部使用分配内存,但是值得注意的是,它经常会定义和使用变量。再一次,这取决于程序:

    • 在vim中,您将使用the :let command来分配内部变量
    • 在bash中,您将使用$ foo='bar'分配一个变量,然后使用$ echo "$foo"读取它
    • 在大多数编程语言中,您使用foo='bar'语法的变体,有时还带有类型声明等

如您所见,bash 使用相同的语法来读取环境变量和其自己的私有变量,这可能会引起一些混乱。

从bash shell执行vim时,环境从父进程(bash)复制到子进程(vim),但是bash的私有内存(包括您可能已定义的变量)不是。

因此,从子进程访问它们将需要父子进程之间的某种进程间通信机制。尽管从技术上讲可行,但该选项未在bash或vim中实现。


解决方案

为使变量可以从vim(或任何分支的进程)访问,您需要将其存在于vim进程的环境中。

有几种选择:

  • $ export foo='bar':这将标记您的变量以导出到随后执行的命令的环境中。在大多数情况下,这就是您想要的。
  • $ foo='bar' vim:这会将变量添加到 this vim命令的环境中。对于疑难解答或单行代码非常有用。
  • $ set -a:正如您在bash manpage中所看到的,这标记了每个后续定义,以导出到后续命令的环境中。从本质上讲,这等效于在每个后续定义之前加上export

走得更远

  • 该问题使用:!echo $foo语法显示foo的值,这是另一个用例。 !实际上是一个转义序列,使您可以从vim执行shell命令。

    但是,vim无法在父shell(您在其中执行vim命令的shell)中执行任何操作,因此它在子进程中创建了一个新的bash shell,在其中执行了echo,并且显示结果。

    在当前情况下,结果大致相同,但是在其他情况下很容易产生误导,因此了解此处发生的情况很重要。

  • 使用expand的{​​{3}}允许查找变量::echo expand("$foo")

    但是,它的工作方式完全不同。

    如果不存在名为foo的内部变量,vim将调用shell进行查找(类似于!会执行的操作)。

    此选项比环境查找慢 ,在大多数情况下不建议使用。

答案 2 :(得分:0)

如果您想在:substitute命令中使用shell中的值,实际上有一种方法。

我不知道它是否可以解决您的需求,但是我们开始吧。

假设我们要用您的Mydir代替PWD

:s/Mydir/\=expand($PWD)/g