5

感谢 PowerShell 表达式模式,PowerShell 有一些很好的方法来反序列化对象,例如:

我的一般期望是,给定表达式的结果应该与在该表达式的同一序列化版本上使用上面列出的反序列化命令之一相同(有关背景,请参阅“在 PowerShell 中保存哈希表”中的ConvertTo-Expression答案对象表示法(PSON)的问题)。
换句话说:

<Expression> <=> Invoke-Command {<Expression>} <=> &([ScriptBlock]::Create('<Expression>'))
<Expression> <=> Invoke-Expression '<Expression>'

例子:

Get-ChildItem <=> &{Get-ChildItem}
Get-ChildItem <=> Invoke-Command {Get-ChildItem}
Get-ChildItem <=> Invoke-Expression 'Get-ChildItem'

1, 2, 3 <=> &{1, 2, 3}
1, 2, 3 <=> Invoke-Command {1, 2, 3}
1, 2, 3 <=> Invoke-Expression '1, 2, 3'

这确实主要适用于每个表达式,但由于 PowerShell 默认展开(枚举)输出这一事实,在表达式包含具有单个项目的数组的情况下,此定义会有所不同:

,1 <≠&gt; Invoke-Command {,1}
,1 <≠&gt; Invoke-Expression ',1'
,"Test" <≠&gt; Invoke-Command {,"Test"}
,"Test" <≠&gt; Invoke-Expression ',"Test"'
@("Test") <≠&gt; Invoke-Command {@("Test")}
@("Test") <≠&gt; Invoke-Expression '@("Test")'
,@("Test") <≠&gt; Invoke-Command {,@("Test")}
,@("Test") <≠&gt; Invoke-Expression ',@("Test")'

有没有办法防止表达式在被调用(反序列化)时展开?

我正在考虑在PowerShell GitHub 上-NoEnumerate请求一个参数(类似于 Write-Outputcmdlet),但这仍然会给不支持参数的呼叫操作员和点源留下问题/问题......Invoke-Expression

4

1 回答 1

0

我找到了一种解决方法来防止(序列化)表达式的默认展开:
将表达式包装在 HashTable 中

<Expression> <=> (Invoke-Command {@{e=<Expression>}})['e']
<Expression> <=> (Invoke-Expression '@{e=<Expression>}')['e']

例子:

Get-ChildItem <=> (Invoke-Command {@{e=Get-ChildItem}})['e']
Get-ChildItem <=> (Invoke-Expression '@{e=Get-ChildItem}')['e']

1, 2, 3 <=> (Invoke-Command {@{e=1, 2, 3}})['e']
1, 2, 3 <=> (Invoke-Expression '@{e=1, 2, 3}')['e']

,1 <=> (Invoke-Command {@{e=,1}})['e']
,1 <=> (Invoke-Expression '@{e=,1}')['e']

我在ConvertFrom-Expression cmdlet 中进一步实现了这一点,它具有以下特性:

  • -NoEnumerate开关以防止具有单个项目的数组展开
  • -NoNewScope切换类似于Invoke-Command
  • 通过管道或参数的多个ScriptBlock和/或String 项-Expression

ConvertFrom-Expression例子:

PS C:>'2*3', {3*4}, '"Test"' | ConvertFrom-Expression
6
12
Test

 

PS C:> (ConvertFrom-Expression ',"Test"' -NoEnumerate) -Is [Array]
True
于 2019-07-12T15:24:12.047 回答