【问题标题】:Unexpected behavior with a string stored in a variable in PowerShell存储在 PowerShell 变量中的字符串的意外行为
【发布时间】:2019-03-09 21:41:59
【问题描述】:

我从 Excel 的 Cells.Find() 方法中得到了一些奇怪的行为:

我正在搜索的变量:

PS > $volumename
vol_01       

PS > $volumename.GetType()

IsPublic IsSerial Name                                     BaseType                                                                                                                                            
-------- -------- ----                                     --------                                                                                                                                            
True     True     String                                   System.Object 

不产生任何结果:

PS > $sheet.Cells.Find($volumename).Row

但如果我手动复制并粘贴该变量的值:

PS > $volumename = "vol_01"
PS > $volumename.GetType()

IsPublic IsSerial Name                                     BaseType                                                                                                                                            
-------- -------- ----                                     --------                                                                                                                                            
True     True     String                                   System.Object 

得到我期望的值:

PS > $sheet.Cells.Find($volumename).Row
198

在我看来,它们在各方面都是完全相同的类型。并非所有情况都会发生这种情况。一些卷名可以很好地通过,而另一些则不能。我确实为这篇文章清理了卷名,因为它有一个客户命名约定。它与上面的格式相同,并且与有效的卷名格式相同。

【问题讨论】:

  • 您是如何在 Excel 工作表中打开 powershell 终端的?
  • 我不是。我在 powershell 中打开 excel 表。
  • 使用[int[]] [char[]] 'hello' | % { '0x{0:x} {1}' -f $_, [char] $_ } 来检查字符串中隐藏的控制字符。
  • @mklement0,很有趣。我在十六进制代码 0xa0 的字符串末尾看到一些无关紧要的不可见字符。我将如何修剪它?字符串替换?

标签: string powershell variables control-characters


【解决方案1】:

以下 sn-p 可用于检查字符串是否有隐藏的控制字符

PS> & { [int[]] [char[]] $Args[0] | % { '0x{0:x} [{1}]' -f $_, [char] $_ } } "vol_01`n"
0x76 [v]
0x6f [o]
0x6c [l]
0x5f [_]
0x30 [0]
0x31 [1]
0xa [
]

第一列是每个字符的Unicode代码点(“ASCII码”),第二列是字符本身,包含在[...]

请注意,我在字符串末尾添加了"`n" - newline character (U+000A) - 其代码点表示为十六进制。号码是0xa

如果与您的情况一样,字符串中唯一不需要的部分是尾随空格,您可以按如下方式删除它们:

$volumename.TrimEnd() # trim trailing whitespace

在您的情况下,尾随空格是0xa0NO-BREAK SPACE (U+00A0).TrimEnd() 也会删除,正如Tom Blodget 指出的那样。


基于上述的简单函数包装器,用于管道输入:

filter debug-Chars { [int[]] [char[]] $_ | % { '0x{0:x} [{1}]' -f $_, [char] $_ } }

使用示例:

"vol_01`n" | debug-Chars

【讨论】:

  • 有问题的代码点是 U+00A0 NO-BREAK SPACE。 .Trim() 和 TrimEnd() 也会删除它。此外,PowerShell char 是 UTF-16 代码单元,而不是 Unicode 代码点(就像 .NET 的其余部分以及自 VB4 和 Java 以来的许多其他环境中一样)。 U+00A0 需要一个 UTF-16 编码单元[char]0x00a0
  • 感谢 NO-BREAK SPACE 更正,@TomBlodget - 我已经相应地更新了答案。至于代码点与代码单元。没错,PowerShell 字符。是 UTF-16 代码单元,但每个代码单元也是一个 Unicode 代码点。但并非每个代码点本身都是 Unicode 字符(因此并非每个 .NET 字符都必须是完整的 Unicode 字符)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-12
  • 2021-10-11
  • 2011-01-07
  • 2015-01-29
相关资源
最近更新 更多