环境

Shell 中的一个常见任务是控制外部应用程序将使用的环境变量。这通常是自动完成的,因为环境被打包,并在外部应用程序启动时提供给它。但有时,我们希望更精确地控制一个应用程序看到的环境变量。

你可以使用env命令查看当前环境变量:

  1. # name type value raw
  2. ──────────────────────────────────────────────────────────────────────────────────────────
  3. 16 DISPLAY string :0 :0
  4. 17 EDITOR string nvim nvim
  5. 28 LANG string en_US.UTF-8 en_US.UTF-8
  6. 35 PATH list<unknown> [list 16 items] /path1:/path2:/...
  7. 36 PROMPT_COMMAND block <Block 197>

在 Nushell 中,环境变量可以是任何值,并且有任何类型(见type列)。 Nushell 中使用的环境变量的实际值在value列下。 你可以直接使用$env变量查询该值,例如,$env.PATH | length。 最后的raw列显示了将被发送到外部应用程序的实际值(详见 环境变量转换 )。

环境最初是由 Nu 的 配置文件 和 Nu 的运行环境创建的。

设置环境变量

有几种方法可以设置环境变量:

let-env

使用let-env命令是最直接的方法:

  1. > let-env FOO = 'BAR'

let-env 类似于 bash 中的 export 命令。

因此,如果你想扩展PATH变量,你可以这样做:

  1. let-env PATH = ($env.PATH | prepend '/path/you/want/to/add')

在这里,我们把指定文件夹前置添加到PATH中的现有路径中,所以它将有最高的优先级。 如果你想给它最低的优先级,你可以使用append命令。

load-env

如果你有一个以上的环境变量需要设置,你可以使用load-env并创建一个键/值对记录(Record),以用于加载多个环境变量:

  1. > load-env { "BOB": "FOO", "JAY": "BAR" }

一次性环境变量

这些变量被定义为只在执行代码块的过程中临时有效。 详情请看 一次性环境变量

调用def-env定义的命令

详情见 从自定义命令中定义环境

使用模块导出

参见 模块 部分了解更多详情。

作用域

当你设置环境变量时,它将只在当前作用域内可用(变量所在的块和它里面的任何块)。

这里有一个小例子来演示环境变量作用域:

  1. > let-env FOO = "BAR"
  2. > do {
  3. let-env FOO = "BAZ"
  4. $env.FOO == "BAZ"
  5. }
  6. true
  7. > $env.FOO == "BAR"
  8. true

目录切换

Shell 中常见的任务是用cd命令来改变目录。 在 Nushell 中,调用cd等同于设置PWD环境变量。 因此,它遵循与其他环境变量相同的规则(例如,作用域)。

一次性环境变量

在 Bash 和其他软件的启发下,有一个常用的简便方法,可以设置一次性环境变量:

  1. > FOO=BAR echo $env.FOO
  2. BAR

你也可以使用with-env来更明确地做同样的事情:

  1. > with-env { FOO: BAR } { echo $env.FOO }
  2. BAR

with-env命令将暂时把环境变量设置为给定的值(这里:变量 “FOO” 被赋为 “BAR” 值)。一旦这样做了, 将在这个新的环境变量设置下运行。

永久性环境变量

你也可以在启动时设置环境变量,使它们在 Nushell 运行期间都可用。 要做到这一点,请在 Nu 配置文件 中设置一个环境变量。 比如:

  1. # In config.nu
  2. let-env FOO = 'BAR'

从自定义命令中定义环境变量

由于作用域规则,在自定义命令中定义的任何环境变量都只存在于该命令的作用域内。 然而,用def-env而不是def定义的命令(它也适用于export def,见 模块)将在调用者一方保留环境设置:

  1. > def-env foo [] {
  2. let-env FOO = 'BAR'
  3. }
  4. > foo
  5. > $env.FOO
  6. BAR

环境变量转换

你可以通过设置ENV_CONVERSIONS环境变量,来在字符串和值之间转换其他环境变量。 例如,默认环境配置环境 - 图1 (opens new window)包括将PATH(和 Windows 上使用的Path)环境变量从一个字符串转换为一个列表。 在 env.nuconfig.nu 配置文件加载后,任何在ENV_CONVERSIONS内指定的现有环境变量将根据其from_string字段被转换为任何类型的值。 外部工具要求环境变量是字符串,因此,任何非字符串的环境变量需要先进行转换: 值->字符串的转换由ENV_CONVERSIONSto_string字段设置,每次运行外部命令时都会进行转换。

让我们用一个例子来说明转换的情况。 把以下内容放在你的config.nu中:

  1. let-env ENV_CONVERSIONS = {
  2. # ... you might have Path and PATH already there, add:
  3. FOO : {
  4. from_string: { |s| $s | split row '-' }
  5. to_string: { |v| $v | str collect '-' }
  6. }
  7. }

现在,在一个 Nushell 实例内执行:

  1. > with-env { FOO : 'a-b-c' } { nu } # runs Nushell with FOO env. var. set to 'a-b-c'
  2. > $env.FOO
  3. 0 a
  4. 1 b
  5. 2 c

你可以看到$env.FOO现在是一个新的 Nushell 实例中的列表,配置已经更新。 你也可以通过以下方式手动测试转换:

  1. > do $env.ENV_CONVERSIONS.FOO.from_string 'a-b-c'

现在,为了测试列表->字符串的转换,运行:

  1. > nu -c '$env.FOO'
  2. a-b-c

因为nu是一个外部程序,Nushell 根据ENV_CONVERSIONS.FOO.to_string翻译了 [ a b c ] 列表,并把它传递给nu进程。 用nu -c运行命令不会加载配置文件,因此FOO的环境转换没有了,它被显示为一个普通的字符串 —— 这样我们可以验证转换是否成功。 你也可以通过do $env.ENV_CONVERSIONS.FOO.to_string [a b c]手动运行这个步骤。

如果我们回头看一下env命令,raw列显示由ENV_CONVERSIONS.<name>.to_string翻译的值,value列显示 Nushell 中使用的值(在FOO的情况下是ENV_CONVERSIONS.<name>.from_string的结果)。 如果这个值不是字符串,并且没有to_string的转换,它就不会被传递给外部(见PROMPT_COMMANDraw列)。 一个例外是PATH(Windows 上的Path)。默认情况下,它在启动时将字符串转换为列表,在运行外部程序时,如果没有指定手动转换,则从列表转换为字符串。

(重要! 环境转换字符串->值发生在 env.nuconfig.nu 被运行之后env.nuconfig.nu 中的所有环境变量仍然是字符串,除非你手动将它们设置为一些其他的值。)

删除环境变量

只有当一个环境变量被设置在当前作用域中时,你才能通过 hide 命令“删除”它:

  1. > let-env FOO = 'BAR'
  2. ...
  3. > hide FOO

隐藏也是有作用域的,这既允许你暂时删除一个环境变量,又可以防止你从子作用域内修改父环境:

  1. > let-env FOO = 'BAR'
  2. > do {
  3. hide FOO
  4. # $env.FOO does not exist
  5. }
  6. > $env.FOO
  7. BAR

关于隐藏的更多细节,请参考 模块