考虑以下Powershell片段:
[Uint64] $Memory = 1GB
[string] $MemoryFromString = "1GB"
[Uint64] $ConvertedMemory = [Convert]::ToUInt64($MemoryFromString)
第3行失败了:
Exception calling "ToUInt64" with "1" argument(s): "Input string was not in a correct format."
At line:1 char:1
+ [Uint64]$ConvertedMemory = [Convert]::ToUInt64($MemoryFromString)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : FormatException
如果我查看$Memory
的内容:
PS C:\> $Memory
1073741824
工作正常。
那么,如何在Powershell中将值“1GB”从字符串转换为UInt64?
答案 0 :(得分:6)
您的问题是ToUint64
无法理解Powershell语法。你可以这样做:
($MemoryFromString / 1GB) * 1GB
由于$MemoryFromString
将在分割之前转换为其数值。
这是有效的,因为在分割时,Powershell尝试使用其规则将字符串转换为数字,而不是将{。}规则转换为ToUInt64
。作为转化的一部分,如果找到GB
后缀并应用规则将"1GB"
字符串展开为1073741824
编辑:或者正如PetSerAl指出的那样,你可以这样做:
($MemoryFromString / 1)
答案 1 :(得分:3)
只有结果变量([uint64] $ConvertedMemory
= ...)的类型约束才能确保($MemoryFromString / 1)
转换为[uint64]
([System.UInt64]
)。
表达式$MemoryFromString / 1
的结果实际上是[int]
([System.Int32]
)类型的结果:
> ('1gb' / 1).GetType().FullName
System.Int32
因此,为了确保表达式本身返回[uint64]
个实例,您必须使用强制转换:
> ([uint64] ('1gb' / 1)).GetType().FullName
System.Int64
请注意计算所需的(...)
,因为[uint64]
仅适用于'1gb'
(因此会失败)。
或者,('1gb' / [uint64] 1)
也可以。
注意:
'1gb' - 0
也会奏效,'1gb' * 1'
(实际上是无操作)或'1gb' + 0
(导致字符串'1gb0'
),因为运营商*
和+
带有字符串 -typed LHS执行字符串操作(分别是复制和连接)。当PowerShell执行隐式号码转换时,包括执行混合数值类型计算和解析源代码中的数字文字时,可以方便地自动选择数字类型为&#34 ;大"足以保存结果。
在隐式字符串到数字转换中,PowerShell可以方便地识别源代码中与文字支持的格式相同的格式:
类型说明符后缀:L
[long]
([System.Int64]
)和D
[decimal]
({1}} [System.Decimal]
);例如,'1L' - 0
产生[long]
请注意, C#使用M
代替D
,而是使用D
来指定[System.Double]
;此外,C#还支持几个额外的后缀。
浮点表示,例如1.23
;请注意, PowerShell只会将.
识别为小数点,无论当前的文化 。
指数表示法;例如,'1.0e3' - 1
会产生999
。
自己的二进制倍增器后缀,kb
,mb
,gb
,tb
,pb
(对于乘数[math]::pow(2, 10)
== 1024
,[math]::pow(2, 20)
== 1048576
,...);例如,'1kb' - 1
产生1023
;请注意,这些后缀是特定于PowerShell的,因此.NET框架编号解析方法不识别它们。
数字转换规则很复杂,但这里有一些关键点:
这是基于我自己的实验。如果我错了,请告诉我
类型由其PS类型加速器表示,并映射到.NET类型,如下所示:
[int]
... [System.Int32]
[long]
... [System.Int64]
[decimal]
... [System.Decimal]
[float]
... [System.Single]
[double]
... [System.Double]
功能
PowerShell 从不自动选择无符号整数类型。
[uint32] 0xffffffff
失败,因为0xffffffff
首先 - 隐式地 - 转换为签名类型[int32]
,产生-1
,作为签名的值,无法转换为 unsigned 类型[uint32]
。L
强制解释为[int64]
,这会产生预期的正值4294967295
,在这种情况下,转化为[uint32]
成功。0x7fffffffffffffff
([long]::maxvalue
)以上的值,但是,在这种情况下,您可以使用字符串转换:[uint64] '0xffffffffffffffff'
PowerShell 根据需要扩展整数类型:
对于十进制整数文字/字符串,扩展超越整数类型到[System.Decimal]
,然后[Double]
< / strong>,根据需要; e.g:
(2147483648).GetType().Name
会产生Int64
,因为该值为[int32]::MaxValue + 1
,因此会隐式加宽为[int64]
。
(9223372036854775808).GetType().Name
会产生Decimal
,因为该值为[int64]::MaxValue + 1
,因此会隐式加宽为[decimal]
。
(79228162514264337593543950336).GetType().Name
会产生Double
,因为该值为[decimal] :: MaxValue + 1 , and was therefore implicitly widened to
[double]`。
对于十六进制(总是整数)文字/字符串,加宽[int64]
:
(0x100000000).gettype().name
会产生Int64
,因为该值为[int32]::MaxValue + 1
,因此会隐式加宽为[int64]
。
0x10000000000000000
,[int64]::MaxValue + 1
,由于十六进制而解释 因此,失败。
注意:以上规则适用于单个文字/字符串,但表达式中的扩展可能会立即扩展到[System.Decimal]
(不考虑[double]
) - 见下文。
PowerShell看似从不自动选择小于的整数类型 :
[decimal]
会产生[int]
(('1' - 0).GetType().FullName
),即使整数System.Int32
适合[int]
甚至1
。计算结果从不使用比任何一个操作数更小的类型:
[int16]
和[byte]
都会产生1 + [long] 1
(即使结果可能适合较小的类型)。也许出乎意料的是, PowerShell会自动选择浮点类型[long] 1 + 1
,以获得大于任一操作数类型的计算结果即使结果 符合更大的整数类型,整数类型也可以:
[long]
会产生[double]
(a ([int]::maxvalue + 1).GetType().FullName
),即使结果符合System.Double
整数。[double]
产生[long]
(a ([int]::maxvalue + [long] 1).GetType().FullName
)。 在计算中包含至少一个浮点类型始终会产生System.Int64
,即使与整数类型混合或使用全部 - [long]
个操作数也是如此:
[double]
和[float]
以及1 / 1.0
和1.0 / 1
以及1 / [float] 1
都会产生[float] 1 / 1
(未加引号)的数字文字 :
十进制整数字面值被解释为以下类型中可以容纳该值的最小值:[float] 1 / [float] 1
&gt; [double]
&gt; [int]
&gt; [long]
强>(!):
[decimal]
会产生[double]
(如上所述,1
是自动选择的最小类型)[int]
(高于[int]
1)会产生214748364
[int]::maxvalue
(高于[long]
1)会产生9223372036854775808
[long]::maxvalue
(高于[decimal]
1)会产生79228162514264337593543950336
十六进制整数字面值被解释为以下类型中可以容纳该值的最小值:[decimal]::maxvalue
&gt; [double]
强>;也就是说,与十进制文字不同,不支持大于[int]
的类型; 警告:具有高位设置的值导致_negative_十进制数,因为PowerShell会自动选择签名的整数类型:
[long]
会产生[long]
0x1
会产生[int]
负值,因为高位设置为:0x80000000
,这是最小值 [int]
数字,如果您考虑签名(-2147483648
)[int]
(比[int]::MinValue
多1位)会产生0x100000000
[int]
(比[long]
中断的<1>多一点,因为0x10000000000000000
是支持的最大类型(&#34) ;数字常量无效&#34;)。
要确保十六进制文字产生正数字,请先使用类型后缀[long]
强制解释为[long]
,然后(可选)强制转换为 unsigned 类型;例如L
会产生[long]
,但请注意,此技术最多只能使用[uint32] 0x80000000L
,即2147483648
;如上所述,使用字符串的转换作为解决方法(例如0x7fffffffffffffff
)。
(总是十进制) 浮点或指数表示法 文字始终解释为[long]::maxvalue
,无论多小:
[uint64] '0xffffffffffffffff'
和[double]
都会产生1.0