Windows PowerShell:仅为单个命令设置环境变量

Windows PowerShell:仅为单个命令设置环境变量,windows,powershell,scripting,variables,environment,Windows,Powershell,Scripting,Variables,Environment,在Linux上,我可以做到: $ FOO=BAR ./myscript 在设置环境变量FOO的情况下调用“myscript” 在PowerShell中是否可以进行类似的操作,即不必首先设置变量、调用命令,然后再次取消设置变量 为了更清楚地了解我的用例,我不想将其作为脚本的一部分。相反,我有一个第三方脚本,我可以使用环境变量控制它的行为,但在本例中,不是命令行参数。所以能够在打字之间切换 $ OPTION=1 ./myscript 及 这将非常方便。您可以将变量的作用域设置为函数和脚本 $sc

在Linux上,我可以做到:

$ FOO=BAR ./myscript
在设置环境变量FOO的情况下调用“myscript”

在PowerShell中是否可以进行类似的操作,即不必首先设置变量、调用命令,然后再次取消设置变量

为了更清楚地了解我的用例,我不想将其作为脚本的一部分。相反,我有一个第三方脚本,我可以使用环境变量控制它的行为,但在本例中,不是命令行参数。所以能够在打字之间切换

$ OPTION=1 ./myscript


这将非常方便。

您可以将变量的作用域设置为函数和脚本

$script:foo = "foo"
$foo
$function:functionVariable = "v"
$functionVariable

如果您想正式使用新变量并声明您的变量,则新变量还具有-scope参数。

通常,最好通过参数而不是 全局(环境)变量。但如果你需要这样做,你可以这样做:

$env:FOO = 'BAR'; ./myscript
稍后可以删除环境变量$env:FOO,如下所示:

Remove-Item Env:\FOO

要实现Unix语法的等效性,您不仅需要设置环境变量,还必须在执行命令后将其重置为以前的值。我通过在PowerShell配置文件中添加类似于以下的函数,完成了对常用命令的此操作

function cmd_special()
{
  $orig_master = $env:app_master
  $env:app_master = 'http://host.example.com'
  mycmd $args
  $env:app_master = $orig_master
}
因此,
mycmd
是一些可执行文件,根据环境变量
app\u master
的值,其运行方式不同。通过定义
cmd_special
,我现在可以使用
app_master
环境变量集从命令行(包括其他参数)执行
cmd_special
。。。在执行命令后,它会被重置(甚至取消设置)

据推测,您也可以对单个调用执行此临时操作

& { $orig_master = $env:appmaster; $env:app_master = 'http://host.example.com'; mycmd $args; $env:app_master = $orig_master }
它确实应该比这更简单,但显然这不是一个由PowerShell支持的用例。也许将来的版本(或第三方函数)将促进这个用例。如果PowerShell有一个cmdlet可以做到这一点,那就太好了,例如:

with-env app_master='http://host.example.com' mycmd

也许一位PowerShell专家可以建议如何编写这样的cmdlet。

我对这个问题有足够的动力,所以我继续写了一个脚本:

用法:

with-env.ps1 FOO=foo BAR=bar your command here

# Supports dot-env files as well
with-env.ps1 .\.env OTHER_ENV=env command here
env.exe FOO=foo BAR=bar your command here

# To use it with dot-env files
env.exe $(cat .env | grep.exe -v '^#') SOME_OTHER_ENV=val your command
另一方面,如果您安装了,您可以使用
env.exe
,这可能比我上面写的快速脚本更健壮

用法:

with-env.ps1 FOO=foo BAR=bar your command here

# Supports dot-env files as well
with-env.ps1 .\.env OTHER_ENV=env command here
env.exe FOO=foo BAR=bar your command here

# To use it with dot-env files
env.exe $(cat .env | grep.exe -v '^#') SOME_OTHER_ENV=val your command

考虑到CMD是Windows内核上的本机CLI(并且仍然是许多工具的自动化界面),您可能正在从CMD提示符或接受CMD控制台语句的界面中使用
PowerShell.exe
执行PowerShell脚本

如果您使用
-File
参数将脚本传递到
powershell.exe
,则不能使用其他powershell代码设置脚本要访问的环境变量,因此您可以在调用
powershell.exe
之前在CMD环境中设置环境变量:

> set foo=bar && powershell.exe -File .\script.ps1
单个
&
也可以工作,但如果
设置因某种原因失败,则允许命令继续。(这可能吗?我不知道。)


此外,将
“foo=bar”
用引号括起来可能更安全,这样就不会将以下内容传递给
设置为变量内容。

在一行中有两种简单的方法:

$env:FOO='BAR'; .\myscript; $env:FOO=''
$env:FOO='BAR'; .\myscript; Remove-Item Env:\FOO

刚才总结了其他答案中的信息(谢谢大家),由于某些原因,这些答案不包含纯一行程序。

您可以通过以下方式运行脚本:

您还可以使用
Start Job
ArgumentList
参数向脚本传递参数:

$jobArgs = @{
    InitializationScript = { $env:FOO = 'BAR' } 
    FilePath             = '.\myscript.ps1'
    ArgumentList         = 'arg1', 'arg2' 
}
Start-Job @jobArgs | Receive-Job -Wait -AutoRemoveJob
优点和缺点

  • 您不必在脚本完成后重置环境变量(这需要
    try
    /
    finally
    才能正确执行,即使存在异常)
  • 环境变量实际上是已启动脚本的本地变量。它不会影响其他可能同时启动的工作
  • 脚本将在自己的、有点隔离的环境中运行。这意味着启动的脚本无法设置主脚本的变量,它必须使用
    写入输出
    与主脚本通信。这可能是优点,也可能是缺点,这取决于用例

我想我的问题是,为什么需要这样做?“我认为有更好的解决办法。这通常不是一个有用的问题,@EBGreen。unixshell中存在该功能这一事实表明,它是有用的。在我的脑海中:控制git用于提交的用户名和电子邮件地址。没有命令行选项,您必须在每个存储库中的~/.gitconfig、.git/config或envars中设置它们。在这些选项中,envars显然更容易动态设置(并方便地覆盖文件中的值)。所以,如果我想在powershell中为一个“git commit”更改我的作者名称,该如何做?完全同意,询问为什么需要这样做是毫无意义的。在Linux上的命令行上执行时,它就像罗宋汤一样常见,我们这些现在被迫忍受powershell(如果有语法噩梦的话,那就是语法噩梦)的人必须不断地寻找显而易见的技术的答案。大多数时候,他们不会;除非你把写长脚本来做一些琐碎的事情算在内,否则powershell中根本就不存在。我对这个shell深感失望……这个功能非常有用。感谢@FranklinYu的链接,但在这一点上,它将是v7.0之后不久的未来版本。我只是想:你不能通过-Command参数生成一个新的PowerShell进程,将scriptblock交给它吗?这样,您就不必在事后清理环境,因为这将包含在子进程中。虽然我在和一个PowerShell MVP谈话