【问题标题】:Can't convert string to int in PowerShell无法在 PowerShell 中将字符串转换为 int
【发布时间】:2019-03-05 15:17:49
【问题描述】:

我正在尝试使用 PowerShell 将字符串转换为整数。然而,它一直告诉我我没有有效的号码,尽管我确定我有。

首先,这是我获取变量的方式,以及类型的打印输出等,以确保有效性:

$obj = (New-Object -TypeName PSCustomObject -Property @{
    LastSaved = $com.GetDetailsOf($_, 155).toString().trim()
})
Write-Host $obj.LastSaved
$datePart,$b,$c = $obj.LastSaved.Split(" ")
Write-Host $datePart
$intVar,$b,$c = $datePart.Split("/")
$intVar = $intVar.Trim()
$intVar -replace '\W', ''
Write-Host $intVar
Write-Host $intVar.GetType()

输出:

5/‎26/‎2016 年 8:09 AM

2016 年 5 月 26 日

5

系统字符串

这是我尝试的第一种转换方法:

[int]$converted = 0
[int]::TryParse($intVar, [ref]$converted)
Write-Host $converted

还有输出:

错误

0

下一个方法:

$converted = [convert]::ToInt32($intVar, 10)

结果:

使用“2”个参数调用“ToInt32”的异常:“找不到任何可识别的数字。”

还有我试过的第三种方法:

$converted = $intVar / 1

结果:

无法将值“‎5”转换为类型“System.Int32”。错误:“输入字符串的格式不正确。”

如果我手动为 $intVar 分配“5”值 ($intVar = "5") 一切正常,所以我认为我如何获得该值肯定存在问题。但我不知道我做错了什么,因为GetType() 说它确实是一个字符串。

编辑:根据 TobyU 的回答,我也尝试过 $intVar = [int]$intVar,结果与

相同

无法将值“‎5”转换为类型“System.Int32”。错误:“输入字符串的格式不正确。”

编辑:另一种方法:

$intVar = [int]::Parse($intVar)

这给出了:

使用“1”个参数调用“Parse”的异常:“输入字符串的格式不正确。”

编辑 3: 显然,正如一些评论者所提到的,存在无效字符。这是Format-Hex 的输出:

           00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000   3F 32 36                                         ?26             

【问题讨论】:

  • 我建议在你的字符串上使用.Trim() 来删除整数之前/之后的任何可能的隐藏字符。
  • @TheIncorrigible1 我更新了我的代码以尝试.Trim()-replace,结果相同(请参阅我的编辑)。
  • 尝试将其发送至Format-Hex 以查看所有内容。正如其他人所提到的,显然某些东西是不可能存在的。
  • 也可以考虑试试-replace '[^\d]'(如果你只是删除,第二个参数是可选的)
  • @Lee_Dailey 啊,我不知道那个方法。我已经用十六进制输出更新了问题。

标签: .net powershell type-conversion


【解决方案1】:

检查问题源文本中的错误消息表明您的字符串包含不可见的LEFT-TO-RIGHT-MARK Unicode character (U+200E),这就是转换失败的原因。

删除该字符将使转换成功,在最简单的情况下,只需消除所有非数字字符即可实现。从字符串:

# Simulate the input string with the invisible control char.
$intStr = [char] 0x200e + '5'

# FAILS, due to the invisible Unicode char.
[int] $intStr # -> ... "Input string was not in a correct format."

# OK - eliminate non-digits first.
# Note the required (...) for proper precedence.
[int] ($intStr -replace '\D') # -> 5

可选阅读:检查字符串的字符:

# Print the code points of the string's characters:
PS> [int[]] [char[]] $intStr
8206  # decimal equivalent of 0x200e, the LEFT-TO-RIGHT-MARK
53    # decimal equivalent of 0x54, the DIGIT FIVE

# Show the code points in hex. format and print the char.
PS> [char[]] $intStr | 
       Select-Object @{ n='CodePoint'; e={ 'U+{0}' -f ([int] $_).ToString('X4') } }, 
                     @{ n='Char';      e={ $_ } }

CodePoint Char
--------- ----
U+200E       ‎
U+0035       5

也可以使用Format-Hex,但格式不易直观解析:

PS> $intStr | Format-Hex -Encoding BigEndianUnicode

                       00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000000000000000   20 0E 00 35                                       ..5            

-Encoding BigEndianUnicode (UTF16-BE) 被使用 - 即使 .NET 字符串使用 Unicode (UTF16-LE) - 所以总是以 byte 为导向的显示会显示首先是 16 位代码单元,读起来更自然。

字节对20 0E是第一个代码单元U+200E(从左到右的标记),00 35是第二个代码单元U+0035(数字5)。

右侧的打印字符的用处有限,因为它们是字节-输入字节的单独解释,它只按预期呈现 8 位范围内的字符(代码点 U+00FF); 0x0 字节表示为 .

【讨论】:

  • @TastesLikeTurkey :) 我的荣幸;请查看我的更新以检查字符串的字符。
  • 我的计算属性转到使用@( @{ ... } ),每个哈希表都在换行符上。
  • @TheIncorrigible1 这为您提供了很大的灵活性,并允许您省略元素之间的,(假设您将它们放在单独的行上),但我更喜欢不使用封闭的@987654339 @ 并使用 , 来终止每个元素行以进行隐式行继续 - 如答案所示。 (无论哪种方式,一个单独的哈希表都可以分布在多行中)。
【解决方案2】:
$intVar = [int]$intVar

在这种情况下应该可以正常工作。

$intVar.GetType() # String
$intVar = [int]$intVar
$intVar.GetType() # Int32

【讨论】:

  • 这也给了我错误Cannot convert value "‎5" to type "System.Int32". Error: "Input string was not in a correct format."
  • 看起来你的值中有一个隐藏字符。
  • 我更新了我的代码以尝试 .Trim()-replace,结果相同(请参阅我的编辑)
猜你喜欢
  • 2018-05-10
  • 2013-06-11
  • 1970-01-01
  • 1970-01-01
  • 2020-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多