【问题标题】:How can I prevent a (serialized) expression to unroll如何防止(序列化)表达式展开
【发布时间】:2019-06-29 10:49:53
【问题描述】:

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

我的一般期望是给定表达式的结果应该与在该表达式的同一序列化版本上使用上面列出的反序列化命令之一相同(有关背景,请参阅'Save hash table in PowerShell object notation (PSON)' 上的ConvertTo-Expression 答案问题)。
换句话说:

<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 <≠> 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")'

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

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

【问题讨论】:

  • 我知道 powershell 在某些情况下会使表达式变平。我不认为序列化是正确的词。那是为了从远程计算机返回对象。序列化的对象没有方法。
  • 我能找到的唯一方法:$a = @(&amp;{,1})
  • @js2010,关于"serialization",所有三个命令都列出了命令:Invoke-Expression、调用运算符 (&amp;([ScriptBlock]::Create('&lt;Expression&gt;'))) 和点源接受纯文本作为描述对象的输入 (可能(或不)来自远程计算机)...
  • @js2010,关于$a = @(&amp;{,1}),这适用于(单值)数组,但会破坏任何非数组的原始定义(例如`valuedtypes`和hashtables)例如'Test' &lt;≠&gt; @(&amp;{'Test'})

标签: powershell expression deserialization unroll


【解决方案1】:

我找到了一种解决方法来阻止(序列化)表达式的默认展开:
将表达式包装在 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 和/或 通过管道或-Expression 参数的字符串项

ConvertFrom-Expression 示例:

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

 

PS C:> (ConvertFrom-Expression ',"Test"' -NoEnumerate) -Is [Array]
True

【讨论】:

    猜你喜欢
    • 2011-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-08
    • 2016-08-29
    • 2019-11-05
    相关资源
    最近更新 更多