在 bash 中,如果我在脚本中定义一个变量(例如,set_var.sh
),我可以选择这些定义在“运行”脚本后是否保留。
这将取决于我如何“运行”脚本,选项是:
sh set_var.sh
(变量不持久化)./set_var.sh
(变量不持久化,同第1点)source set_var.sh
(变量持久化)
这与是否在 set_var.sh
中导出到环境的变量无关。
对于 PS 和 $env
变量,是否可以使用 PowerShell 5.1 脚本实现与上述第 1 项和第 3 项相同的功能?
有关插图,请参见下面的 (1)。
编辑:
根据 Mathias R. Jessen 的回答,与上述第 3 项等效的是“点采购”。 还有一种“中间”情况(上面没有指出,也许还有一种方法可以在 bash 中实现),其中环境变量持续存在但 PS 变量不存在。
我的脚本:
# set_var.ps1
$env:TEST_VAR = 'test_var'
$TEST_VAR2 = 'test_var2'
我检查的内容:
> $env:TEST_VAR ; $TEST_VAR2 ;
> . .\set_var.ps1
> $env:TEST_VAR ; $TEST_VAR2 ;
test_var
test_var2
> Remove-Variable TEST_VAR2 ; Remove-Item env:TEST_VAR ;
> $env:TEST_VAR ; $TEST_VAR2 ;
> .\set_var.ps1
> $env:TEST_VAR ; $TEST_VAR2 ;
test_var
> Remove-Item env:TEST_VAR ;
> $env:TEST_VAR ; $TEST_VAR2 ;
> & .\set_var.ps1
> $env:TEST_VAR ; $TEST_VAR2 ;
test_var
(1) 持久/非持久变量示例
我有包含以下内容的脚本 set_var.sh
:
#!/bin/bash
export TEST_VAR=test_var
TEST_VAR2=test_var2
然后下面的命令证明了我的观点:
$ echo $TEST_VAR ; echo $TEST_VAR2
$ sh set_var.sh ; echo $TEST_VAR ; echo $TEST_VAR2
$ source set_var.sh ; echo $TEST_VAR ; echo $TEST_VAR2
test_var
test_var2
$ echo $TEST_VAR ; echo $TEST_VAR2
test_var
test_var2
$ env | grep TEST_VAR
TEST_VAR=test_var
$ unset TEST_VAR ; unset TEST_VAR2
$ echo $TEST_VAR ; echo $TEST_VAR2
$ ./set_var.sh ; echo $TEST_VAR ; echo $TEST_VAR2
$ echo $TEST_VAR ; echo $TEST_VAR2
最佳答案
关于您的修改:
这是脚本的直接调用/通过&
调用 - 这与 sh
不同/bash
,运行进程中 - 保留环境变量更改,但不保留脚本中的常规变量。[1]
使用 &
使用脚本 block ( { ... }
) 代替脚本文件进行简洁演示:
PS> & { $foo = 'bar'; $env:foo = 'bar-env' }; "[$foo]", "[$env:foo]"
[] # regular variable in the script [block] scope went out of scope
[bar-env] # environment variable is visible to caller (the whole *process*)
至于 1 的 PowerShell 等价物。 ( sh set_var.sh
)
和 2. ( ./set_var.sh
):
对 PowerShell CLI 的显式调用(Windows PowerShell 中的 powershell.exe
,PowerShell [Core] 中的 pwsh
,v6+):需要在 子进程。
注意:以下示例使用pwsh
, 但同样适用于 powershell.exe
(其 CLI 与 pwsh
基本相同,只是向后者添加了一些参数)。
在最简单的情况下,使用 -File
(这是 PowerShell [Core] 中的隐含参数,但在 Windows PowerShell 中是必需的):
pwsh -File set_var.ps1 # PowerShell v6+: same as: pwsh set_var.ps1
但是请注意,您只能通过这种方式从脚本中获得文本输出(字符串),而不是丰富的对象 PowerShell 通常支持。
接收对象的最简单方法 - 仅可从 内部 PowerShell[2] 获取 - 是传递一个脚本 block ,在其中调用脚本,这会自动使 CLI 输出脚本输出对象的 XML 序列化表示,并导致这些表示自动反序列化通过调用 session :
pwsh { .\set_var.ps1 }
注意:
.\
前缀是必需的,因为 PowerShell - 按照设计,作为一项安全功能 - 不允许从当前目录 仅文件名 运行脚本。使用 CLIXML 格式的基于 XML 的序列化(也用于 PowerShell 的远程处理和后台作业)在类型保真度方面有限制;除了 .NET 基本类型和少数知名类型外,您会得到
[pscustomobject]
- 基于原始对象的近似值 - 参见this answer .
[1] 但是,PowerShell 确实提供了跨 session 范围边界设置变量的能力,例如$global:foo = 'bar'
设置 session 全局变量或 Set-Variable foo bar -Scope 1
在调用者(父级)范围内设置一个变量(从脚本的顶级范围调用时也将是全局范围)。
[2] 从 PowerShell 外部,您可以明确请求 CLIXML 格式(基于 XML 的对象序列化格式)的输出,即 -of Xml
CLI 参数,但您必须自己解析 XML 并从中重建对象。
关于bash - PowerShell 通过脚本在环境变量范围内的灵活性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62932372/