Powershell 为什么字符和字符串的“-lt”行为不同?
最近,我开始考虑将Powershell 为什么字符和字符串的“-lt”行为不同?,powershell,comparison,operators,string-comparison,Powershell,Comparison,Operators,String Comparison,最近,我开始考虑将-lt或-gt与字符串一起使用。我的答案是基于这样的说法,即-lt一次比较每个字符串中的一个字符,直到ASCII值不等于另一个为止。在这一点上,结果(较低/相等/较大)决定。根据该逻辑,“Less”-lt“Less”应返回True,因为L的ASCII字节值低于L,但它不: [System.Text.Encoding]::ASCII.GetBytes("Less".ToCharArray()) 76 101 115 115 [System.Text.Encoding]::ASC
-lt
或-gt
与字符串一起使用。我的答案是基于这样的说法,即-lt
一次比较每个字符串中的一个字符,直到ASCII值不等于另一个为止。在这一点上,结果(较低/相等/较大)决定。根据该逻辑,“Less”-lt“Less”
应返回True
,因为L
的ASCII字节值低于L
,但它不:
[System.Text.Encoding]::ASCII.GetBytes("Less".ToCharArray())
76
101
115
115
[System.Text.Encoding]::ASCII.GetBytes("less".ToCharArray())
108
101
115
115
"Less" -lt "less"
False
似乎我遗漏了一个关键部分:测试不区分大小写
#L has a lower ASCII-value than l. PS doesn't care. They're equal
"Less" -le "less"
True
#The last s has a lower ASCII-value than t. PS cares.
"Less" -lt "lest"
True
#T has a lower ASCII-value than t. PS doesn't care
"LesT" -lt "lest"
False
#Again PS doesn't care. They're equal
"LesT" -le "lest"
True
然后,我尝试测试char与单个字符串:
[int][char]"L"
76
[int][char]"l"
108
#Using string it's case-insensitive. L = l
"L" -lt "l"
False
"L" -le "l"
True
"L" -gt "l"
False
#Using chars it's case-sensitive! L < l
([char]"L") -lt ([char]"l")
True
([char]"L") -gt ([char]"l")
False
比较是如何工作的,因为它显然不是通过使用ASCII值来实现的,为什么字符和字符串的行为会有所不同?不太确定在处理字符串/字符时,除了比较之外,在这里发布什么都是正确的。如果你想要一个有序的比较,做一个有序的比较,你会得到基于这个的结果 及 不确定在此添加什么来帮助澄清
另请参见:不太确定在这里发布的内容,但在处理字符串/字符时,比较都是正确的。如果你想要一个有序的比较,做一个有序的比较,你会得到基于这个的结果 及 不确定在此添加什么来帮助澄清 另请参阅:非常感谢他所有宝贵的意见 tl;博士:
和-lt
通过Unicode码点以数字方式比较-gt
实例[char]
- 令人困惑的是,
、-ilt
、-clt
、-igt
——尽管它们只对字符串操作数有意义,但这是PowerShell语言本身的一个怪癖(见下图)-cgt
- 令人困惑的是,
- 相比之下,比较
(及其别名-eq
),不区分大小写地比较-ieq
实例,这通常但不一定像不区分大小写的字符串比较([char]
再次严格地进行数字比较)-ceq
/-eq
最终也会进行数字比较,但首先会使用不变区域性将操作数转换为大写等效数;因此,此比较并不完全等同于PowerShell的字符串比较,后者还将所谓的兼容序列(不同字符,甚至被认为具有相同含义的序列;请参阅)视为相等李>-ieq
- 换句话说:PowerShell特例仅使用
操作数执行[char]
/-eq
的行为,其执行方式几乎是,但与不区分大小写的字符串比较不同-ieq
- 这种区别会导致违反直觉的行为,例如
和[char]'A'-eq[char]'A'
都返回[char]'A'-lt[char]'A'
$true
- 为了安全起见:
- 如果要进行数字(Unicode码点)比较,请始终强制转换为
[int]
- 如果要进行字符串比较,请始终强制转换为
李>[string]
- 如果要进行数字(Unicode码点)比较,请始终强制转换为
PowerShell通常有用的运算符重载有时会很棘手 请注意,在数字上下文中(无论是隐式还是显式),PowerShell将字符(
[char]
([System.char]
)实例)按其Unicode码点(非ASCII)进行数字处理
[char]
的与众不同之处在于,除了使用-eq
/-ieq
之外,它的实例在数字上与Unicode码点进行比较
,ceq
和-lt
直接通过Unicode码点进行比较,并且-反直觉地-ilt,-gt
,-clt
和-igt
:-cgt
(及其别名-eq
)首先将字符转换为大写,然后比较生成的Unicode码点:-ieq
i
或c
来明确指定大小写匹配行为不足以强制字符串比较,即使概念上的运算符,如-ceq
,-ieq
,-clt
,-ilt
,-cgt
,-igt
仅对字符串有意义
有效地,在比较[char]
操作数时,当应用于-lt
和-gt
时,i
和c
前缀被忽略;事实证明(与我最初的想法不同),这是一个一般的PowerShell陷阱——请参见下面的解释
另一方面:-lt
和-gt
字符串比较中的逻辑不是数字,而是基于排序顺序(一种以人为中心的排序方式,独立于代码点/字节值),在.NET术语中,排序由区域性控制(默认情况下为当前有效的方法,或将区域性参数传递给方法)。正如@PetSerAl在评论中所展示的(与我最初所说的不同)
"L" -clt "l"
False
"l" -clt "L"
True
[string]::Compare('L','l')
returns 1
[string]::Compare("L","l", [stringcomparison]::Ordinal)
returns -32
[char] 'A' -eq 65 # $true, in the 'Basic Latin' Unicode range, which coincides with ASCII
[char] 'Ā' -eq 256 # $true; 0x100, in the 'Latin-1 Supplement' Unicode range
[char] 'A' -lt [char] 'a' # $true; Unicode codepoint 65 ('A') is less than 97 ('a')
[char] 'A' -eq [char] 'a' # !! ALSO $true; equivalent of 65 -eq 65
# Distinct Unicode characters U+2126 (Ohm Sign) and U+03A9 Greek Capital Letter Omega)
# ARE recognized as the "same thing" in a *string* comparison:
"Ω" -ceq "Ω" # $true, despite having distinct Unicode codepoints
# -eq/ieq: with [char], by only applying transformation to uppercase, the results
# are still different codepoints, which - compared numerically - are NOT equal:
[char] 'Ω' -eq [char] 'Ω' # $false: uppercased codepoints differ
# -ceq always applies direct codepoint comparison.
[char] 'Ω' -ceq [char] 'Ω' # $false: codepoints differ
"10" -cgt "2" # $false, because "2" comes after "1" in the collation order
10 -cgt 2 # !! $true; *numeric* comparison still happens; the `c` is ignored.