2013-08-31 18 views
5

Khi làm việc với một ổ đĩa được ánh xạ tới một chia sẻ Linux, tên tệp phân biệt chữ hoa chữ thường. PowerShell xử lý như mong đợi, nhưng tôi muốn sắp xếp đầu ra theo cách tương tự với thứ tự sắp xếp được sử dụng trong miền "C", có nghĩa là sắp xếp theo giá trị ký tự theo thứ tự tăng dần từ U + 0000 đến U + 10FFFF (ví dụ như '0foo' đi trước 'foo' và 'foo' đi trước 'bar' và 'bar' đi trước 'foo')Thay đổi hành vi sắp xếp đối tượng

Để minh họa cho vấn đề:

PS > gci Z:\foo | sort -casesensitive 
xyz 
Xyz 
XYZ 
yZ 
YZ 

Output mong muốn:

XYZ 
Xyz 
YZ 
xyz 
yZ 

Tôi đã thử đặt biến văn hóa của chuỗi hiện tại thành [System.Globalization.CultureInfo]::InvariantCulture , nhưng tôi đã không thành công:

$thrd = [Threading.Thread]::CurrentThread 
$thrd.CurrentCulture = [Globalization.CultureInfo]::InvariantCulture 
$thrd.CurrentUICulture = $thrd.CurrentCulture 

Tôi thậm chí đóng khi tôi cho rằng nó có liên quan đến thông tin văn hóa hay tôi thực sự đi xa? Có ai có bất kỳ ý tưởng nơi tôi nên bắt đầu? Tôi đoán tôi cần phải tạm thời tạo ra một thể hiện CultureInfo có hành vi tôi mong muốn, nhưng nó chỉ có getters như xa như CompareInfo đi, chưa kể tôi không chắc chắn về cách quá tải các chức năng CompareInfo.Compare mà Sort-Object yêu cầu sử dụng chức năng PowerShell. Hay đây có phải là nguyên nhân bị mất vì điều đó là không thể?

Sửa

Ít nhất, nó sẽ có thể để sắp xếp với ký tự chữ hoa đầu tiên, như trong XYZ, xyz, xyz, YZ, YZ?

+1

'Bình thường' là so sánh trong .NET so sánh các ký tự dựa trên giá trị điểm mã của chúng (xem thêm [Khác biệt giữa biến thể bất biến và so sánh chuỗi thông thường] (http://stackoverflow.com/a/492885/2495)). [Câu trả lời của Mitul] (http://stackoverflow.com/a/18544765/2495) với ['[StringComparer] :: Ordinal'] (http://msdn.microsoft.com/en-us/library/system.stringcomparer .ordinal.aspx) trông giống như sự lựa chọn tốt nhất. –

Trả lời

7

Tôi đã cố gắng thực sự khó tìm nếu có cách thay đổi chính phương thức sort-object nhưng không hoạt động. Nhưng một cái gì đó tương tự như tôi đã có thể thực hiện bằng cách sử dụng lớp StringComparer tĩnh như được minh họa trong msdn example này.

Để trả lời phần cuối cùng của bạn,

At the very least, would it be possible to sort with uppercase characters first, as in XYZ, Xyz, xyz, YZ, yZ? 

[System.StringComparer]::InvariantCultureIgnoreCase là câu trả lời của bạn. Để thấy sự khác biệt, tôi đã thử tất cả các phiên bản khác nhau bên dưới.

$arr = "0foo","xyz","Xyz","YZ","yZ","XYZ","Foo","bar" 
$list = New-Object System.Collections.ArrayList 
$list.AddRange($arr) 

Write-host "CurrentCulture" 
$list.Sort([System.StringComparer]::CurrentCulture); 
$list 
<# --------CurrentCulture-------- 
CurrentCulture 
0foo 
bar 
Foo 
xyz 
Xyz 
XYZ 
yZ 
YZ 
#> 

Write-Host "CurrentCultureIgnoreCase" 
$list.Sort([System.StringComparer]::CurrentCultureIgnoreCase); 
$list 

<# --------CurrentCultureIgnoreCase-------- 
CurrentCultureIgnoreCase 
0foo 
bar 
Foo 
XYZ 
Xyz 
xyz 
YZ 
yZ 
#> 

Write-Host "InvariantCulture" 
$list.Sort([System.StringComparer]::InvariantCulture); 
$list 
<# --------InvariantCulture-------- 
InvariantCulture 
0foo 
bar 
Foo 
xyz 
Xyz 
XYZ 
yZ 
YZ 
#> 

Write-Host "InvariantCultureIgnoreCase" 
$list.Sort([System.StringComparer]::InvariantCultureIgnoreCase); 
$list 

<# --------InvariantCultureIgnoreCase-------- 

InvariantCultureIgnoreCase 
0foo 
bar 
Foo 
XYZ 
Xyz 
xyz 
YZ 
yZ 
#> 

Write-Host "Ordinal" 
$list.Sort([System.StringComparer]::Ordinal); 
$list 

<# --------Ordinal-------- 
Ordinal 
0foo 
Foo 
XYZ 
Xyz 
YZ 
bar 
xyz 
yZ 
#> 

Write-Host "OrdinalIgnoreCase" 
$list.Sort([System.StringComparer]::OrdinalIgnoreCase); 
$list 

<# --------OrdinalIgnoreCase-------- 
OrdinalIgnoreCase 
0foo 
bar 
Foo 
xyz 
XYZ 
Xyz 
yZ 
YZ 
#> 
+0

Rất kỹ lưỡng. Tôi đã hy vọng tôi sẽ không cần phải làm bất cứ điều gì như thế này, nhưng rõ ràng ý tưởng sắp xếp là khá hạn chế, ngay cả trong PowerShell. Cảm ơn nhiều. –