如何在Powershell中分配和引用包含方括号的环境变量 [英] How to assign and reference environment variables containing square brackets in Powershell

查看:282
本文介绍了如何在Powershell中分配和引用包含方括号的环境变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

未指定PSDrive时,将执行以下操作:

When the PSDrive is not specified, the following works:

${[foo]}="bar"
echo ${[foo]}

但是以下方法不起作用

$env:${[foo]}="bar"
At line:1 char:1 
+ $env:${[foo]}="bar"
+ ~~~~~
Variable reference is not valid. ':' was not followed by a valid variable name character. Consider using ${} to delimit the name.
At line:1 char:6
+ $env:${[foo]}="bar"
+      ~~~~~~~~~~~~~~
Unexpected token '${[foo]}="bar"' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : InvalidVariableReferenceWithDrive

${env:[foo]}="bar"
Cannot find path 'env:[foo]' because it does not exist. 
At line:1 char:1
+ ${env:[foo]}="bar"
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (env:[foo]:String) [], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound

以下作品,尽管我很好奇它是否有简短的语法:

The following works, though I am curious if there's short hand syntax for it:

Set-Item -LiteralPath env:${[foo]} -Value "bar"
Get-Item -LiteralPath env:${[foo]} | % {$_.Value}

但是以下方法不起作用:

However the following does not work:

Set-Item -LiteralPath env:${[foo]2} -Value "bar"
Set-Item : Cannot process argument because the value of argument "name" is null. Change the value of argument "name" to a non-null value.      
At line:1 char:1
+ Set-Item -LiteralPath env:${[foo]2} -Value "bar"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:String) [Set-Item], PSArgumentNullException
    + FullyQualifiedErrorId : SetItemNullName,Microsoft.PowerShell.Commands.SetItemCommand

推荐答案

从PowerShell Core 6.2.0起编写

原因是PowerShell处理以下内容:

The reason is that PowerShell treats the following:

${<drive>:<name>}

就像您已指定:

Get-Content -Path <drive>:<name>  # or, with assignment, Set-Content -Path ...

这种表示法-尽管经常与Env:驱动器(例如$env:Path)一起使用-鲜为人知,它是名为 命名空间变量表示法通用范例 em> ,这在此答案中进行了解释.

This notation - though often used with the Env: drive (e.g., $env:Path) - is little-known as a general paradigm named namespace variable notation, which is explained in this answer.

问题是使用-Path而不是-LiteralPath ,因为-Path 将其参数解释为通配符表达式

The problem is the use of -Path rather than -LiteralPath, because -Path interprets its argument as a wildcard expression.

因此,${env:[foo]}中的[foo]-而不是按原样使用-被解释为与单个字符匹配的通配符表达式,该字符是fo ([foo]是一个字符集或范围([...]),与内部的任何(不同)字符匹配-请参见

Therefore, the [foo] in ${env:[foo]} - rather than being used as-is - is interpreted as a wildcard expression that matches a single character that is either f or o ([foo] is a character set or range ([...]) that matches any one of the (distinct) characters inside - see about_Wildcards).

分配 时,Set-Content -Path的逻辑要求基于通配符的路径解析为已有的东西,即使您通常是显式创建环境变量不是必需的;例如${env:NoSuchVarExistsYet} = 'new'可以正常工作.

On assigning to ${env:[foo]}, the logic of Set-Content -Path requires that a wildcard-based path resolve to something existing, even though you're generally not required to explicitly create environment variables; e.g., ${env:NoSuchVarExistsYet} = 'new' works just fine.

解决方法:

使用 double (!)-`-通配符元字符转义:

Use double(!)-`-escaping of the wildcard metacharacters:

# Namespace variable notation only works with if you
# double(!)-backtick-escape the wildcard metacharacters:

# Assign to / implicitly create env. var '[foo]'
${env:``[foo``]} = 'bar'

# Get its value.
${env:``[foo``]}

注意:

  • Escaping shouldn't be required at all, because there is no good reason to treat paths that conceptually identify a given, known item as wildcard expressions - see this GitHub issue.

需要转义 double `是一个附加的怪癖-参见此GitHub问题.

That double `-escaping is needed is an added quirk - see this GitHub issue.

另一种解决方法-一种不涉及转义的方法-使用
Set-Content -LiteralPath env:[foo] barGet-Content -LiteralPath env:[foo],但这既冗长又缓慢.

Another workaround - one that doesn't involve escaping - is to use
Set-Content -LiteralPath env:[foo] bar and Get-Content -LiteralPath env:[foo], but that is both verbose and slow.

关于您尝试过的其他语法变体:

$env:${[foo]}="bar"

由于您的变量引用不是整体上由{...}括起来的 (初始的$除外),因此:之后的标记仅允许包含以下字符: 不需要转义-并且${}都违反了该规则.

Since your variable reference isn't {...}-enclosed as a whole (except for the initial $), the token that follows the : is only allowed to contain characters that do not require escaping - and $, { and } all violate that rule.

  • {...}-包围整个路径-${env:[foo]}-解决了语法问题,但遇到了上面详述的问题.
  • {...}-enclosing the entire path - ${env:[foo]} - solves the syntax problem, but runs into the problem detailed above.

Set-Item -LiteralPath env:${[foo]} -Value "bar"

这通常不会起作用,因为字符串扩展是在此处预先应用的-就像您已通过"env:${[foo]}"一样:引用(常规)名为${[foo]}的变量被扩展 (用其值替换),并且实际上附加在文字env:之前,之前将结果传递给Set-Item.

This does not work in general, because string expansion is applied beforehand here - it is as if you had passed "env:${[foo]}": the reference to a (regular) variable named ${[foo]} is expanded (replaced with its value) and in effect appended to literal env:, before handing the result to Set-Item.

如果不存在这样的常规变量,则Set-Item看到的只是env:(因为不存在的变量默认为$null,它在字符串上下文中成为空字符串),这将导致错误由于缺少变量名.

If such a regular variable doesn't exist, what Set-Item sees is just env: (because non-existent variables default to $null, which becomes the empty string in a string context), which causes an error due to the lack of variable name.

相反,以下代码将设置一个名为unrelated的环境变量:

By contrast, the following would set an environment variable named unrelated instead:

# Create a regular variable literally named '[foo]'.
${[foo]} = 'unrelated'

# !! The following sets env:unrelated, i.e., env. var 'unrelated',
# !! due to the string expansion that is performed on the -LiteralPath
# !! argument up front.
Set-Item -LiteralPath env:${[foo]} bar

$env:unrelated # -> 'bar'

Get-Item -LiteralPath env:${[foo]}
的情况相同 Set-Item -LiteralPath env:${[foo]2} -Value "bar".

The same applies to Get-Item -LiteralPath env:${[foo]} and
Set-Item -LiteralPath env:${[foo]2} -Value "bar".

这篇关于如何在Powershell中分配和引用包含方括号的环境变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆