Chỉ định thứ tự sắp xếp với LC_COLLATE để chữ thường nằm trước chữ hoa


16

Đưa ra các tập tin:

$ cat file
1
a
C
B
2
c
3
A
b

Theo mặc định sortsẽ:

$ sort file
1
2
3
a
A
b
B
c
C

Với LC_COLLATE=Cnhư vậy sẽ sắp xếp bằng chữ in hoa trước chữ thường:

$ LC_COLLATE=C sort file
1
2
3
A
B
C
a
b
c

Có thể có được sắp xếp để đảo ngược thứ tự trường hợp, đó là chữ số, chữ thường sau đó viết hoa?

Câu trả lời:


8

Tôi không biết bất kỳ địa phương nào, theo mặc định, sắp xếp theo thứ tự đó. Giải pháp là tạo một miền địa phương tùy chỉnh với thứ tự sắp xếp tùy chỉnh. Nếu bất cứ ai, bốn năm sau, muốn sắp xếp theo kiểu tùy chỉnh, đây là mẹo.

Phần lớn các địa phương không chỉ định thứ tự sắp xếp riêng của họ, mà sao chép thứ tự sắp xếp được xác định trong /usr/share/i18n/locales/iso14651_t1_commonđó là những gì bạn sẽ muốn chỉnh sửa. Thay vì thay đổi thứ tự sắp xếp cho gần như mọi miền địa phương bằng cách sửa đổi bản gốc iso14651_t1_common, tôi khuyên bạn nên tạo một bản sao. Chi tiết về cách thứ tự sắp xếp hoạt động và cách tạo một miền địa phương tùy chỉnh trong $HOMEthư mục của bạn mà không có quyền truy cập root được tìm thấy trong câu trả lời này cho một câu hỏi tương tự .

Hãy xem cách aAđược sắp xếp dựa trên các mục của họ trong iso14651_t1_common:

<U0061> <a>;<BAS>;<MIN>;IGNORE # 198 a
<U0041> <a>;<BAS>;<CAP>;IGNORE # 517 A

bBtương tự nhau:

<U0062> <b>;<BAS>;<MIN>;IGNORE # 233 b
<U0042> <b>;<BAS>;<CAP>;IGNORE # 550 B

Chúng ta thấy rằng trên đường chuyền đầu tiên, cả hai aAcó biểu tượng đối chiếu <a>, trong khi cả hai bBcó biểu tượng đối chiếu <b>. Kể từ khi <a>xuất hiện trước <b>trong iso14651_t1_common, aAđược buộc trước bB. Vượt qua thứ hai không phá vỡ các mối quan hệ vì cả bốn ký tự đều có ký hiệu đối chiếu <BAS>, nhưng trong lần chuyển thứ ba, các mối quan hệ được giải quyết vì biểu tượng đối chiếu cho các chữ cái viết thường <MIN>xuất hiện trên dòng 3467, trước biểu tượng đối chiếu cho các chữ cái viết hoa <CAP>(dòng 3488) . Vì vậy, thứ tự sắp xếp kết thúc lên như a, A, b, B.

Hoán đổi các ký hiệu đối chiếu thứ nhất và thứ ba sẽ sắp xếp các chữ cái trước theo trường hợp (thấp hơn trên), sau đó theo dấu ( <BAS>có nghĩa là không có dấu), sau đó theo thứ tự bảng chữ cái. Tuy nhiên , cả hai <MIN><CAP>đến trước các chữ số, vì vậy điều này sẽ có tác dụng không mong muốn là đặt các chữ số sau các chữ cái.

Cách dễ nhất để giữ các chữ số đầu tiên trong khi làm cho tất cả các chữ cái viết thường xuất hiện trước tất cả các chữ cái viết hoa là buộc tất cả các chữ cái buộc trong lần so sánh đầu tiên bằng cách đặt tất cả các chữ cái bằng <a>. Để đảm bảo rằng chúng sắp xếp theo thứ tự abc trong trường hợp, hãy thay đổi biểu tượng đối chiếu cuối cùng từ IGNOREbiểu tượng đối chiếu đầu tiên hiện tại. Theo mô hình này, asẽ trở thành:

<U0061> <a>;<BAS>;<MIN>;<a> # 198 a

A sẽ trở thành:

<U0041> <a>;<BAS>;<CAP>;<a> # 517 A

b sẽ trở thành:

<U0062> <a>;<BAS>;<MIN>;<b> # 233 b

B sẽ trở thành:

<U0042> <a>;<BAS>;<CAP>;<b> # 550 B

và như vậy cho phần còn lại của các chữ cái.

Khi bạn đã tạo phiên bản tùy chỉnh iso14651_t1_common, hãy làm theo các hướng dẫn trong câu trả lời được liên kết ở trên để biên dịch ngôn ngữ tùy chỉnh của bạn.


6

Cài đặt LC_COLLATE=Ckhông phải lúc nào cũng đủ để sắp xếp chữ hoa trước chữ thường. Bạn có thể cần phải thiết lập LC_ALL=C.

Điều đó cũng sẽ tính đến các ký tự không phải là chữ và số và thậm chí không in được, nhưng nếu bạn không muốn có các tùy chọn -d-i(được mô tả trong man sort) sẽ tắt nó đi.

Nó có thể sẽ thất bại nặng nề với đầu vào đa bào, chẳng hạn như UTF-8 với các ký tự không phải ASCII.

Để có chữ thường (theo thứ tự) trước chữ hoa (theo thứ tự), cách tốt nhất tôi có thể nghĩ đến đó không liên quan đến việc phá vỡ một ngôn ngữ lập trình chính thức là đảo ngược trường hợp của tất cả các chữ cái trước khi sắp xếp và đảo ngược chúng sau đó

tr 'a-zA-Z' 'A-Za-z' < file | LC_ALL=C sort | tr 'a-zA-Z' 'A-Za-z'

2

Tôi không phải là chuyên gia nhưng tôi chưa bao giờ thấy miền địa phương xác định đối chiếu như thế này. AFAIK đối chiếu này chỉ ở C, dựa trên các giá trị ASCII . (Thông thường tôi sẽ chỉ giải quyết điều này bằng một kịch bản.)

Tuy nhiên, tôi chưa bao giờ thực hiện điều này nhưng bạn có thể muốn xem các trang web localedef (1)locale (5) để hiểu cách xác định địa phương và cuối cùng xác định địa điểm của riêng bạn.

Cũng đừng quên rằng nếu có bất kỳ dấu phụ hoặc ký tự đặc biệt nào, ngôn ngữ C sẽ không đối xử với họ như bạn muốn. Ví dụ, nó sẽ không đặt ágần ahoặc Łgần L. Trong những trường hợp như vậy, ngôn ngữ bản địa của ngôn ngữ có thể là điểm khởi đầu tốt hơn.


0

Tôi tin rằng câu trả lời là không cần thay đổi LC_COLLATE (có nghĩa là để chức năng làm hành vi mặc định):

tập tin sắp xếp

Điều này hoạt động trên Linux; vui lòng tham khảo phần trợ giúp của bạn để biết lệnh trong trường hợp bạn đang dùng Unix và chạy một phiên bản khác. -f được định nghĩa là trường hợp bỏ qua.

Cảm ơn đã sửa chữa nhanh chóng (& kỳ quặc) và chỉnh sửa ngữ pháp bị đặt sai chỗ, Stephen Rauch.


-1
LC_COLLATE="en_US.UTF-8" sort file

Điều này không sắp xếp chữ thường trước chữ hoa? ideone.com/Gtyg4Z
iiSeymour

Hmm, trong trường hợp của tôi, nó đã sử dụng ví dụ của bạn.
unxnut

4
@unxnut Điều này không chính xác. Nếu không có dấu chấm phẩy, lệnh sẽ đặt môi trường cho sort, nhưng với dấu chấm phẩy, biến là cục bộ của trình bao và không ảnh hưởng đến hành vi của sort. Dấu chấm phẩy có thể được giữ nguyên như là nếu biến cũng được xuất, nhưng điều đó cũng sẽ ảnh hưởng đến các lệnh khác.
Anders Sjöqvist
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.