如何防止(序列化)表达式展开

iRo*_*Ron 5 powershell expression deserialization unroll

由于使用PowerShell表达模式,PowerShell提供了一些不错的方法来反序列化对象,例如:

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

<Expression> <=> Invoke-Command {<Expression>} <=> &([ScriptBlock]::Create('<Expression>'))
<Expression> <=> Invoke-Expression '<Expression>'
Run Code Online (Sandbox Code Playgroud)

例子:

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'
Run Code Online (Sandbox Code Playgroud)

对于几乎每个表达式而言,确实确实存在这种情况,但是由于PowerShell默认情况下会展开(枚举)输出,因此在表达式包含具有单个项目的数组的情况下,此定义会有所不同:

,1 <?> Invoke-Command {,1}
,1 <?> Invoke-Expression ',1'
,"Test" <?> Invoke-Command {,"Test"}
,"Test" <?> Invoke-Expression ',"Test"'
@("Test") <?> Invoke-Command {@("Test")}
@("Test") <?> Invoke-Expression '@("Test")'
,@("Test") <?> Invoke-Command {,@("Test")}
,@("Test") <?> Invoke-Expression ',@("Test")'
Run Code Online (Sandbox Code Playgroud)

无论如何,有没有一种方法可以防止在调用(反序列化)表达式时展开表达式?

我正在考虑在PowerShell GitHub上请求一个-NoEnumerate参数(类似于 Write-Outputcmdlet),但这仍然会给不支持参数的调用运算符和点源提供问题/问题...Invoke-Expression

iRo*_*Ron 0

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

<Expression> <=> (Invoke-Command {@{e=<Expression>}})['e']
<Expression> <=> (Invoke-Expression '@{e=<Expression>}')['e']
Run Code Online (Sandbox Code Playgroud)

例子:

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']
Run Code Online (Sandbox Code Playgroud)

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

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

ConvertFrom-Expression例子:

PS C:>'2*3', {3*4}, '"Test"' | ConvertFrom-Expression
6
12
Test
Run Code Online (Sandbox Code Playgroud)

 

PS C:> (ConvertFrom-Expression ',"Test"' -NoEnumerate) -Is [Array]
True
Run Code Online (Sandbox Code Playgroud)