如何防止(序列化的)表达式展开
How can I prevent a (serialized) expression to unroll
感谢 PowerShell 表达式模式,PowerShell 有一些很好的反序列化对象的方法,例如:
Invoke-Expression
cmdlet
Invoke-Command
cmdlet
- 调用操作员
&
- dot sourcing 一个 PowerShell 脚本文件
我的一般期望是给定表达式的结果应该与在该表达式的相同序列化版本上使用上面列出的反序列化命令之一相同(有关背景,请参阅 ConvertTo-Expression answer on the 'Save hash table in PowerShell object notation (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 <≠> 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")'
有没有办法防止表达式在无论如何被调用(反序列化)时被展开?
我正在考虑请求一个 -NoEnumerate
参数(类似于 Write-Output
cmdlet) for the Invoke-Expression
on the PowerShell GitHub,但仍然会为调用运算符和点保留 issue/question采购不支持参数...
我找到了防止默认展开(序列化)表达式的解决方法:
将表达式包装在哈希表中:
<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
- Multiple ScriptBlock and/or 通过管道或
-Expression
参数 的字符串项
ConvertFrom-Expression
示例:
PS C:>'2*3', {3*4}, '"Test"' | ConvertFrom-Expression
6
12
Test
PS C:> (ConvertFrom-Expression ',"Test"' -NoEnumerate) -Is [Array]
True
感谢 PowerShell 表达式模式,PowerShell 有一些很好的反序列化对象的方法,例如:
Invoke-Expression
cmdletInvoke-Command
cmdlet- 调用操作员
&
- dot sourcing 一个 PowerShell 脚本文件
我的一般期望是给定表达式的结果应该与在该表达式的相同序列化版本上使用上面列出的反序列化命令之一相同(有关背景,请参阅 ConvertTo-Expression answer on the 'Save hash table in PowerShell object notation (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 <≠> 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")'
有没有办法防止表达式在无论如何被调用(反序列化)时被展开?
我正在考虑请求一个 -NoEnumerate
参数(类似于 Write-Output
cmdlet) for the Invoke-Expression
on the PowerShell GitHub,但仍然会为调用运算符和点保留 issue/question采购不支持参数...
我找到了防止默认展开(序列化)表达式的解决方法:
将表达式包装在哈希表中:
<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
- Multiple ScriptBlock and/or 通过管道或
-Expression
参数 的字符串项
ConvertFrom-Expression
示例:
PS C:>'2*3', {3*4}, '"Test"' | ConvertFrom-Expression
6
12
Test
PS C:> (ConvertFrom-Expression ',"Test"' -NoEnumerate) -Is [Array]
True