我正在跑步
'S-tst','ssrst','srst2','s-zaa','s-a','s-zf' | Sort-Object
我不应该得到
的回报s-a
s-tst
s-zaa
s-zf
srst2
ssrst
但我得到以下内容:
s-a
srst2
ssrst
S-tst
s-zaa
s-zf
这怎么可能? sort-object在整理时只查看字母吗?有没有办法用特殊字符排序?
答案 0 :(得分:3)
此行为是设计使然,但并不总是人们想要/期望的。如果您希望按ASCII顺序对每个字符进行排序,请使用以下命令:
Add-Type @"
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
public class SimpleStringComparer: IComparer, IComparer<string>
{
private static readonly CompareInfo compareInfo = CompareInfo.GetCompareInfo(CultureInfo.InvariantCulture.Name);
public int Compare(object x, object y)
{
return Compare(x as string, y as string);
}
public int Compare(string x, string y)
{
return compareInfo.Compare(x, y, CompareOptions.OrdinalIgnoreCase);
}
public SimpleStringComparer() {}
}
"@
[string[]]$myList = 's-a','s-a1','s''a','s''a1', 'sa','sa1','s^a','S-a','S-a1','S''a','S''a1', 'Sa','Sa1','S^a'
[System.Collections.Generic.List[string]]$list = [System.Collections.Generic.List[string]]::new()
$list.AddRange($myList)
[SimpleStringComparer]$comparer = [SimpleStringComparer]::new()
$list.Sort([SimpleStringComparer]::new())
$list
输出:
s'a
S'a
s'a1
S'a1
s-a
S-a
s-a1
S-a1
sa
Sa
sa1
Sa1
s^a
S^a
更多信息
注释中的Per @TessellatingHeckler ,您可以通过将字符串转换为char数组来按字符代码(序号)顺序对字符串进行排序。但是,它仍然以可能意外的方式处理连字符和撇号(因为这些字符被忽略):
$myList = 's-a','s-a1','s''a','s''a1', 'sa','sa1','s^a','S-a','S-a1','S''a','S''a1', 'Sa','Sa1','S^a'
$myList | Sort-Object -Property { [char[]] $_ }
s'a
S'a
s-a
S-a
s'a1
S'a1
s-a1
S-a1
s^a
S^a
sa
Sa
sa1
Sa1
当前的排序行为是设计使然。 PowerShell似乎实现了“Word排序”。这在此处记录:https://msdn.microsoft.com/en-us/library/windows/desktop/dd318144(v=vs.85).aspx#SortingFunctions
除了忽略连字符和撇号(除非比较其他相同的字符串),此类还将标点字符视为字母数字之前的字符,并处理带有重音符号的字母。可以这样看一个简单的演示:
32..255 | %{[string][char][byte]$_} | sort
要定义其他排序行为,目前您可能需要深入了解.Net,如下所示:
Add-Type @"
using System;
using System.Runtime.InteropServices;
using System.Collections;
public class NumericStringComparer: IComparer
{
//https://msdn.microsoft.com/en-us/library/windows/desktop/bb759947%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
[DllImport("shlwapi.dll")]
public static extern int StrCmpLogicalW(string psz1, string psz2);
public int Compare(object x, object y)
{
return Compare(x as string, y as string);
}
public int Compare(string x, string y)
{
return StrCmpLogicalW(x, y);
}
public NumericStringComparer() {}
}
"@
[System.Collections.ArrayList]$myList = 's-a','s-a1','s''a','s''a1', 'sa','sa1','s^a','S-a','S-a1','S''a','S''a1', 'Sa','Sa1','S^a', , '100a','1a','001a','2a','20a'
$myList.Sort([NumericStringComparer]::new())
$myList -join ', '
上面按照Windows资源管理器的方式对字符串进行排序(即将前导数字视为数值):
s'a, s'a1, S'a, s-a, S-a, S-a1, S'a1, s-a1, S^a, s^a, 1a, 001a, 2a, Sa, Sa1, sa, sa1, 20a, 100a
我已提交功能建议,以便在Sort-Object
上提供更多PS友好解决方案。见https://github.com/PowerShell/PowerShell/issues/4098