我希望以下脚本块能够执行并返回类型byte
和int
的数字,但是引号内的所有内容都只是字符串而不是脚本。
$a=(&{Param($t);"[$t]`$num=10;`$num+=2;`$num"} byte)
$a
# OUTPUTS STRING [byte]$num=10;$num+=2;$num
# NOT NUMBER 12
$ty="int"
$b=(&{"[$ty]`$num=5;`$num+=2;`$num"})
$b
# OUTPUTS STRING [int]$num=5;$num+=2;$num
# NOT NUMBER 7
我如何使其按预期工作? 谢谢
答案 0 :(得分:2)
当用引号引起来时(请参见about_quoting_rules),您正在创建一个字符串:
"[$t]`$num=10;`$num+=2;`$num"
因为这就是您要组装的东西,也就是要返回的东西。
我假设您正在尝试转换为特定类型(整数/字节):
[$t]`$num=10
您可以改用LanguagePrimitives.ConvertTo
方法,因为它将为您完成此操作:
[System.Management.Automation.LanguagePrimitives]::ConvertTo(Object, Type)
我先定义脚本块,然后分别调用它:
$a={ codehere }
& $a param1 param2
随身携带所有东西:
$a={Param($t,$num);$num=[System.Management.Automation.LanguagePrimitives]::ConvertTo($num, $t);$num+2}
& $a byte 5
答案 1 :(得分:2)
补充James C.'s helpful answer,它很好地解释了问题,并包含一个有局限性的解决方案 [1] 和替代解决方案:
隔离使用的脚本块确实就像匿名函数一样(它们也是脚本和命名函数的基础)。
虽然无法使用非文字类型名称进行广播 /类型约束,但是您可以使用-as
个具有类似效果的运算符:
PS> & { param($t) $num = 10; $num+=2; $num -as $t } byte # !! use -as $t on OUTPUT
12 # type is [byte]
注意事项:
与PowerShell强制转换不同,-as
运算符是文化敏感的-对于某些类型,但对于其他类型则不是:例如,它对[datetime]
是文化敏感的,但不适用于[double]
如果无法进行转换,则-as
会悄悄返回$null
,因此您可能必须明确处理这种情况。
由于-as
不能用于类型约束变量,因此后续操作可以更改值的数据类型。
$num = 10 -as [byte]
之后加上$num += 2
,确实会发生这种情况:加法会将类型隐式更改为[int]
。-as
运算符应用于输出,或在必要时应用于每个中间操作。
+=
之类的复合运算符,其中-as
不能按预期运行;例如,使用$num += 2 -as [byte]
代替$num = ($num + 2) -as [byte]
。顺便说一句:如果 New-Variable
支持类型约束,则可以按照New-Variable -Type $t -Name num -Value 10
的方式进行选择;当前(自Windows PowerShell v5.1 / PowerShell Core 6.1.0起)没有,但是may in the future。
或者,用 注意事项: 仅在可以完全控制或信任其内容的字符串上使用此技术,因为可以用这种方式构造任意命令。 此外,出于可维护性考虑,此技术仅适用于小段代码。 [1] [scriptblock]::Create()
从字符串表示形式创建脚本块 ,该脚本块允许您将类型名称“烘焙”到字符串中:>
PS> & ([scriptblock]::Create('[{0}] $num=10; $num+=2; $num' -f 'byte'))
12 # type is [byte]
[System.Management.Automation.LanguagePrimitives]::ConvertTo()
并不完全等同于强制转换,因为它没有涵盖"dynamic objects that provide their own conversions."