Powershell -Unique æ 转换为 ae



这是一个非常简单的示例

$Test = @('ae','æ')
$Test | Select-Object -Unique

输出

ae

这里发生了什么,我该如何避免。显然,我不想"ae";等于";æ";

如注释中所述,您当前的区域性设置将aeæ标识为相等,因此它只返回输入数组中的第一个。

如果你反转订单,你会得到æ

$Test = @('æ','ae')
$Test | Select-Object -Unique
# æ

您可以检查PowerShell使用的区域性如下:

PS> Get-Culture
LCID             Name             DisplayName
----             ----             -----------
2057             en-GB            English (United Kingdom)

尽管请注意,根据@mktlement0的评论,PowerShell并没有在所有事情上都一致地使用这种区域性。。。

事实证明,当前的区域性确实适用于Select Object-Unique(它目前出乎意料地(总是)区分大小写)。PowerShell在区域性不变性方面似乎有一个分裂的个性:[string]强制转换、字符串插值和字符串相关运算符(>除外)使用不变的区域性,而cmdlet使用当前区域性。

无论如何,与其说是一种文化意识的比较,不如说你想要的是一种"序数";比较-有关更多详细信息,请参阅顺序字符串操作:

顺序比较是字符串比较,其中在没有语言解释的情况下比较每个字符串的每个字节;例如;窗口";不匹配";Windows";。

(扩展为ae,不等于æ)

我在PowerShell中找不到一种惯用的方法来做到这一点(你可以用Set-Culture更改区域性,但我尝试过的所有方法仍然将ae视为æ),但如果你想更好地控制值的比较方式,你可以像下面这样进入Linq:

PS> $data = @( "ae", "æ" )
PS> [System.Linq.Enumerable]::Distinct([string[]]$data, [System.StringComparer]::Ordinal )
ae
æ

然后你就有了一大堆不同的方法来比较字符串:

https://learn.microsoft.com/en-us/dotnet/api/system.stringcomparer?view=net-6.0#属性

  • CurrentCulture-获取一个StringComparer对象,该对象使用当前区域性的单词比较规则执行区分大小写的字符串比较。

  • CurrentCultureIgnoreCase-获取StringComparer对象,该对象使用当前区域性的单词比较规则执行不区分大小写的字符串比较。

  • InvariantCulture-获取StringComparer对象,该对象使用不变区域性的单词比较规则执行区分大小写的字符串比较。

  • InvariantCultureIgnoreCase-获取StringComparer对象,该对象使用不变区域性的单词比较规则执行不区分大小写的字符串比较。

  • 序号-获取执行区分大小写的序号字符串比较的StringComparer对象。

  • OrdinalIgnoreCase-获取执行不区分大小写的序数字符串比较的StringComparer对象。

,您甚至可以实现自己的:

class FirstLetterComparer : System.Collections.Generic.IEqualityComparer[string] {
[bool]Equals([string]$x, [string]$y) { return $x[0] -eq $y[0]; }
[int]GetHashCode([string] $x) { return $x[0].GetHashCode(); }
}
# returns the first item in the list that starts with each distinct character.
# note that "abb" is omitted because it starts with the same first letter as "aaa"
# so it's not "first letter distinct".
$data = @( "aaa", "abb", "bbb" )
[System.Linq.Enumerable]::Distinct([string[]]$data, [FirstLetterComparer]::new() )
# aaa
# bbb

添加mclayton的优秀答案,并提供背景信息

  • 虽然使用cmdlets(如Select-ObjectPowerShell)确实使用当前区域性,但在某些上下文中,它使用了不变区性,尤其是-eq/-ne运算符-请参阅此答案。

  • PowerShell有两个不同的版本,它们在手头的行为方面有所不同,这取决于它们所基于的.NET版本:

    • Windows PowerShell,旧版,随附Windows版本,其最新也是最终版本是5.1,该版本建立在旧版、仅限Windows的.NET Framework上,该版本使用NSL(国家语言支持)获取特定于区域性的信息。

    • PowerShell(Core)7+,它构建在跨平台的.NET 5+版本上,该版本现在默认使用ICU(Unicode国际组件)库-尽管在Windows上,您可以选择仍使用NLS。

      • 注意事项:对于特定于区域性的设置,如默认小数位数([cultureinfo]::CurrentCulture.NumberFormat.NumberDecimalDigits),实际上仍使用NLS设置;请参阅.NET全球化和ICU以及GitHub第81853期

请继续阅读以了解详细信息。


æ是由字母ae形成的连字。

  • Windows PowerShell/NLS:

    • 连接æ被认为等价于大多数培养物中组成字母的序列外:

      • 其中æ本身被用作字符
      • 并且而不是被认为等价于其组成字母的序列
    • 这些例外情况是(只列出了所谓的中性(非特定国家)文化,而没有列出它们的国家品种):

      • da(丹麦语)
      • is(冰岛语)
      • kl
      • nb(挪威语Bokmål)
      • nn(挪威语尼诺斯克)
      • 否(挪威语)
      • se(北萨米语)
      • sma(萨米语(南部))
      • smj(萨米语(卢勒))
      • smn(萨米语(伊纳里语))
      • sms(萨米语(Skolt))
    • 其他连字在所有培养基中具有多字母等价物,例如œoe;还有一些连字的多字母等价物是而不是其组成字母的序列,但现代等价物,例如德语ß(源自sz)被认为等价于ss

  • PowerShell(核心)7+/ICU

    • 至少在PowerShell 7.2.4的ICU版本中,连字通常在字符串比较中似乎从未被视为与其组成字母等效

最新更新