为什么"zzz"-le"~~~"是假的?

Ros*_*ser 4 powershell

正如标题所说,为什么会发生这种情况?

PS C:\temp> "zzz" -le "~~~"
False

PS C:\temp> "~~~" -le "zzz"
True
Run Code Online (Sandbox Code Playgroud)

"〜"是最后一个ASCII字符的下一个.我无法理解"z"之前的校对.

Bac*_*its 6

这是因为~(代字号)是变音符号,默认比较是语言比较,而不是序数.语法比较在排序时忽略变音符号.这都是Unicode中所有内容的结果.

尝试:

PS C:\> $x = @('aaa','~~~','zzz')
PS C:\> [System.Array]::Sort($x)
PS C:\> $x
~~~
aaa
zzz
PS C:\> [System.Array]::Sort($x,[System.StringComparer]::Ordinal)
PS C:\> $x
aaa
zzz
~~~
Run Code Online (Sandbox Code Playgroud)

C#中的类似答案就在这里.

这是一个更大的比较,使用en-US文化与一些具有变音标记的字符串:

PS C:\> $x = @("0","9","a","A","á","Á","ab","aB","Ab","áb","Áb","Æ","z","Z","~")
PS C:\> [Array]::Sort($x)
PS C:\> $x
~
0
9
a
A
á
Á
ab
aB
Ab
áb
Áb
Æ
z
Z
PS C:\> [Array]::Sort($x,[StringComparer]::Ordinal)
PS C:\> $x
0
9
A
Ab
Z
a
aB
ab
z
~
Á
Áb
Æ
á
áb
Run Code Online (Sandbox Code Playgroud)

那么,哪个是正确的?它将取决于您的应用程序,但.Net Framework默认基于文化的比较.

据我所知,字符串比较默认[System.StringComparer]::CurrentCulture为区分大小写和[System.StringComparer]::CurrentCultureIgnoreCase不区分大小写.我不知道有什么方法可以直接改变这个.即使使用不变文化似乎也不会影响事物:

PS C:\> [System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::InvariantCulture
PS C:\> [System.Array]::Sort($x)
PS C:\> $x
~~~
aaa
zzz
PS C:\> $x[0] -le $x[1]
True
Run Code Online (Sandbox Code Playgroud)

要强制进行序数比较,请使用System.String.CompareOrdinal:

[System.String]::CompareOrdinal($StringA,$StringB)
Run Code Online (Sandbox Code Playgroud)

如果结果是否定的,则$StringA小于$StringB.
如果结果为零,则$StringA等于$StringB.
如果结果是积极的,则$StringA大于$StringB.

因此,这个:

'zzz' -le '~~~'
Run Code Online (Sandbox Code Playgroud)

与序数比较相当:

PS C:\> [System.String]::CompareOrdinal('zzz','~~~') -le 0
True
Run Code Online (Sandbox Code Playgroud)

  • @RossPresser查看我的更新.您可以使用`String.CompareOrdinal`强制对字符串进行序数比较. (2认同)

bri*_*ist 5

简短的回答是:因为它使用[String]::Compare()并返回相同的结果.

答案越长:它不是ASCII值比较.它取决于文化信息和比较选项,默认情况下使用Word排序.

比较使用当前文化来获取特定于文化的信息,例如套管规则和单个字符的字母顺序.例如,文化可以指定某些字符组合被视为单个字符,或者以特定方式比较大写和小写字符,或者字符的排序顺序取决于其前面或后面的字符.

使用单词排序规则进行比较.有关word,string和ordinal排序的更多信息,请参阅 System.Globalization.CompareOptions.

例子

[string]::Compare('z','~')  
# 1

[string]::Compare('~','z')  
# -1

[string]::Compare('z','~',[cultureinfo]::CurrentCulture,[System.Globalization.CompareOptions]::Ordinal)  
# -4

[string]::Compare('~','z',[cultureinfo]::CurrentCulture,[System.Globalization.CompareOptions]::Ordinal)  
# 4
Run Code Online (Sandbox Code Playgroud)