通过脚本在环境变量范围内使用PowerShell的灵活性 [英] PowerShell flexibility in scope of environment variables via scripts
问题描述
在bash中,如果我在脚本内定义一个变量(例如 set_var.sh
),则可以选择在运行后这些定义是否仍然存在。剧本。
这将取决于我如何运行脚本,选项为:
In bash, if I define a variable inside a script (say, set_var.sh
), I can choose whether those definitions persist after "running" the script.
This will depend on how I "run" the script, the options being:
-
sh set_var.sh
(变量不持久) -
./ set_var.sh
(变量不持久,与第1点相同) -
source set_var.sh
(变量仍然存在)
sh set_var.sh
(variables do not persist)./set_var.sh
(variables do not persist, same as point 1)source set_var.sh
(variables persist)
这与导出到环境的变量无关或不在 set_var.sh
中。
This is irrespective from the variable being exported to the environment or not in set_var.sh
.
可以使用PowerShell 5.1脚本实现与上述第1项和第3项相同的功能,对于PS和 $ env
变量?
Can the same as items 1 and 3 above be achieved with PowerShell 5.1 scripts, for both PS and $env
variables?
有关示例,请参见下面的(1)。
For an illustration see (1) below.
编辑:
根据Mathias R. Jessen的回答,等同于上述项目#3 点采购。
还有一个中间情况(上面没有指出,也许还有一种方法可以使它在bash中得到实现),其中环境变量仍然存在,而PS变量却没有。
As per answer by Mathias R. Jessen, the equivalent to item #3 above is "dot sourcing". There is also an "intermediate" case (not identified above, perhaps there is also a way to get this in bash), where environment variables persist but PS variables don't.
我的脚本:
# 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
,其内容如下:
I have script set_var.sh
with the following contents:
#!/bin/bash
export TEST_VAR=test_var
TEST_VAR2=test_var2
然后以下命令证明了我的观点:
Then the following commands prove my point:
$ 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
推荐答案
为了补充 Mathias的有用答案:
关于您的修改:
它是脚本的直接调用/通过&
调用-与 sh不同
/ bash
,在进程中运行 -保留环境变量更改,但不保留常规变量 [1]
It is a script's direct invocation / invocation via &
- which, unlike in sh
/ bash
, runs in-process - preserves environment-variable changes, but not regular variables in the script.[1]
在 script块中使用&
( {...}
)代替脚本文件进行简洁的演示:
Using &
with a script block ({ ... }
) in lieu of a script file for a succinct demonstration:
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*)
与PowerShell等效为1。( sh set_var.sh
)
和2。( ./ set_var.sh
):
显式调用PowerShell CLI ( Windows PowerShell中的 powershell.exe
,在PowerShell [Core],v6 +版本中, pwsh
):需要在子进程 中运行脚本。
An explicit call to the PowerShell CLI (powershell.exe
in Windows PowerShell, pwsh
in PowerShell [Core], v6+): is needed to run a script in a child process.
注意:以下示例使用 pwsh
,但 powershell.exe
也是如此(其CLI与 pwsh
,仅向后者添加了一些参数。)
Note: The following examples use pwsh
, but the same applies to powershell.exe
(whose CLI is a mostly identical to pwsh
's, with only a few parameters having been added to the latter).
在最简单的情况下,使用 -File
(这是PowerShell [Core]中的隐含参数,但在Windows PowerShell中是必需的):
In the simplest case, use -File
(which is the implied parameter in PowerShell [Core], but is required in Windows PowerShell):
pwsh -File set_var.ps1 # PowerShell v6+: same as: pwsh set_var.ps1
但是请注意,您只会以这种方式从脚本中获得文本输出(字符串),而不是PowerShell通常支持的丰富对象。
Note, however, that you'll only get textual output (strings) from the script this way rather than the rich objects that PowerShell normally supports.
接收对象的最简单方法-仅在 inside PowerShell中可用 [2] -是要传递一个脚本块 ,而不是在其中调用脚本,这将自动使CLI输出脚本输出对象的CLI输出XML序列化表示,并使这些表示成为
The simplest way to receive objects instead - available from inside PowerShell only[2] - is to pass a script block in which the script is called instead, which automatically makes the CLI output XML-serialized representations of the script's output objects, and causes these representations to be automatically deserialized by the calling session:
pwsh { .\set_var.ps1 }
注意:
-
.\
前缀是必需的,因为PowerShell(根据设计,作为安全功能)不允许运行纯文件名从当前目录。
The
.\
prefix is necessary, because PowerShell - by design, as a security feature - does not permit running scripts by mere file name from the current directory.
使用CLIXML格式的基于XML的序列化-也用于PowerShell的远程处理和后台作业-对类型保真度有限制 ;除了.NET基本类型和一些众所周知的类型之外,您将获得原始对象的基于 [pscustomobject]
的 approximations -请参见此答案。
The XML-based serialization using the CLIXML format - which is also used for PowerShell's remoting and background jobs - has limits with respect to type fidelity; except for .NET primitive types and a handful well-known types, you get [pscustomobject]
-based approximations of the original objects - see this answer.
[1]但是,PowerShell提供了跨会话范围边界设置变量的功能,例如 $ global:foo ='bar'
设置会话全局变量或 Set-Variable foo bar -Scope 1
在调用者的(父)范围内设置变量(从脚本的顶级范围调用时也将是全局范围)。
[1] However, PowerShell does offer the ability to set variables across in-session scope boundaries, e.g. $global:foo = 'bar'
to set a session-global variable or Set-Variable foo bar -Scope 1
to set a variable in the caller's (parent) scope (which when called from a script's top-level scope would also be the global scope).
[2]在PowerShell外部,您可以显式请求CLIXML格式(基于XML的对象序列化格式)的输出,即使用 -Xml
CLI参数,但您必须自己解析XML并从中重建对象。
[2] From outside of PowerShell, you can explicitly request output in CLIXML format (the XML-based object-serialization format), namely with the -of Xml
CLI parameter, but you'll have to parse the XML yourself and reconstruct objects from it.
这篇关于通过脚本在环境变量范围内使用PowerShell的灵活性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!