Sự khác biệt giữa các tùy chọn --general-numeric-sort và --numeric-sort trong gnu sort


113

sortcung cấp hai loại sắp xếp số. Đây là từ trang người đàn ông:

   -g, --general-numeric-sort
          compare according to general numerical value

   -n, --numeric-sort
          compare according to string numerical value

Có gì khác biệt?


17
Lưu ý rằng tài liệu đầy đủ sortkhông phải là mantrang mà là infotrang ( info sort).
a3nm

Câu trả lời:


85

Sắp xếp số tổng quát so sánh các số dưới dạng số nổi, điều này cho phép ký hiệu khoa học, ví dụ 1.234E10 nhưng chậm hơn và có thể bị lỗi làm tròn (1.2345678 có thể đến sau 1.2345679), sắp xếp số chỉ là một sắp xếp chữ cái thông thường biết 10 đến sau 9.

Xem http://www.gnu.org/software/coreutils/manual/html_node/sort-invocation.html

'-g' '--general-numeric-sort' '--sort = general-numeric' Sắp xếp theo số, sử dụng strtod hàm C chuẩn để chuyển đổi tiền tố của mỗi dòng thành số dấu chấm động có độ chính xác kép. Điều này cho phép các số dấu phẩy động được chỉ định trong ký hiệu khoa học, như 1.0e-34 và 10e100. Ngôn ngữ LC_NUMERIC xác định ký tự dấu thập phân. Không báo cáo lỗi tràn, dòng dưới hoặc lỗi chuyển đổi. Sử dụng trình tự đối chiếu sau: Các dòng không bắt đầu bằng số (tất cả được coi là bằng nhau). NaN (giá trị “Không phải số”, trong số học dấu phẩy động IEEE) theo thứ tự nhất quán nhưng phụ thuộc vào máy. Trừ vô cùng. Số hữu hạn theo thứ tự số tăng dần (với -0 và +0 bằng nhau). Cộng vô cùng.

Chỉ sử dụng tùy chọn này nếu không có lựa chọn thay thế; nó chậm hơn nhiều so với --numeric-sort (-n) và nó có thể mất thông tin khi chuyển đổi sang dấu phẩy động.

'-n' '--numeric-sort' '--sort = numeric' Sắp xếp theo số. Số bắt đầu mỗi dòng và bao gồm các khoảng trống tùy chọn, dấu '-' tùy chọn và không hoặc nhiều chữ số có thể được phân tách bằng dấu phân cách hàng nghìn, theo sau là ký tự dấu thập phân và không hoặc nhiều chữ số. Một số trống được coi là '0'. Ngôn ngữ LC_NUMERIC chỉ định ký tự dấu phẩy thập phân và dấu phân cách hàng nghìn. Theo mặc định, khoảng trống là một khoảng trắng hoặc một tab, nhưng ngôn ngữ LC_CTYPE có thể thay đổi điều này.

So sánh là chính xác; không có lỗi làm tròn.

Cả ký hiệu '+' hàng đầu và hàm mũ đều không được công nhận. Để so sánh các chuỗi như vậy về mặt số, hãy sử dụng tùy chọn --general-numeric-sort (-g).


2
Cảm ơn. Lạ là người đàn ông và các trang thông tin không có điều này trong đó. Tôi cũng không biết về gnu.org/software/coreutils/manual/html_node/index.html .
Trenton

6
Công cụ này không phù hợp với tôi. Tôi đang sắp xếp tệp có cột thứ ba có nội dung như R1 R2 R10 R15. Sử dụng một trong hai -k3.2nhoặc -k3.2g, nó đang sắp xếp R10trước đây R2. Cách sắp xếp là từ vựng, không phải số. Tôi hy vọng nó sẽ coi trường từ ký tự thứ hai trở đi là một số.
Kaz

6
@Kaz: sortthông số kỹ thuật chính của. thực sự là byzantine - viết tắt của nó là: (các) khoảng trống trước trường được coi là một phần của trường , do đó, char. chỉ mục 1 trỏ đến ô trống (đầu tiên) trước trường, không phải ký tự đầu tiên thực tế của trường. Hậu tố ký tự. chỉ mục với bđể khắc phục sự cố này, tức là: -k 3.2bn,3(lưu ý rằng tùy chọn toàn cục không hoạt động trong trường hợp này). Cũng lưu ý thêm , điều này đảm bảo rằng chỉ trường thứ 3 được sử dụng - không có chỉ mục trường thứ 2 đó, phần còn lại của toàn bộ dòng được sử dụng. -b,3
mklement0

11

Bạn nên cẩn thận với ngôn ngữ của mình. Ví dụ: bạn có thể có ý định sắp xếp một số thực (như 2,2) trong khi ngôn ngữ của bạn có thể mong đợi việc sử dụng dấu phẩy (như 2,2).

Như đã báo cáo trong diễn đàn này , bạn có thể có kết quả sai khi sử dụng cờ -n hoặc -g.

Trong trường hợp của tôi, tôi sử dụng:

LC_ALL=C sort -k 6,6n file

để sắp xếp cột thứ 6 chứa:

2.5
3.7
1.4

để có được

1.4
2.5
3.7

2
Ngay cả với LANG = C, tôi không thể -nnhận ra dấu phẩy là dấu phân cách hàng nghìn - “1,000” được coi giống như “1”.
Scott

1
Đó phải là LC_ALL = C.
Stuart P. Bentley

@Scott: Thật vậy, hàng nghìn dấu phân cách KHÔNG được nhận dạng: sortsử dụng logic tiền tố dài nhất: phần dài nhất của dòng / khóa mà nó nhận dạng là một số được sử dụng; trong ngôn ngữ sử dụng .làm ký tự cơ số, nó sẽ dừng đọc tại ,.
mklement0

@ StuartP.B Bentley: LC_ALL=Cthực sự là sự lựa chọn mạnh mẽ nhất ; tuy nhiên, nếu LC_ALLxảy ra không đặt cược, LANG=Ccũng sẽ hoạt động.
mklement0

1
Điểm tốt, nhưng LANG=C sort -k 6,6n filevừa đơn giản hơn và cũng bản địa hóa ảnh hưởng của việc thiết lập biến môi trường LANGcho lệnh cụ thể.
mklement0

0

Ngoài câu trả lời được chấp nhận có đề cập đến -gký hiệu khoa học cho phép , tôi muốn hiển thị phần có nhiều khả năng gây ra hành vi không mong muốn.

Với -g:

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=en_US.UTF-8 sort -g myfile
baa
--inf
--inf  
--inf- 
--inf--
--inf-a
--nnf
nnf--
   nnn  
tnan
zoo
   naN
Nana
nani lol
-inf
-inf--
-11
-2
-1
1
+1
2
+2
0xa
11
+11
inf

Nhìn vào zoo, ba điều quan trọng ở đây:

  • Dòng bắt đầu bằng NAN(ví dụ Nananani lol) hoặc -INF(một dấu gạch ngang, không phải --INF) di chuyển đến cuối nhưng trước các chữ số. Trong khi INFdi chuyển đến các chữ số cuối cùng sau vì nó có nghĩa là vô cùng .

  • Các NAN, INF-INFtrường hợp nhạy cảm .

  • Các dòng luôn luôn bỏ qua khoảng trắng từ hai bên NAN, INF, -INF (không phân biệt LC_CTYPE). Các bảng chữ cái khác có thể bỏ qua khoảng trắng từ hai bên tùy thuộc vào ngôn ngữ LC_COLLATE(ví dụ: LC_COLLATE=fr_FR.UTF-8bỏ qua nhưng LC_COLLATE=us_EN.UTF-8không bỏ qua).

Vì vậy, nếu bạn đang sắp xếp chữ và số tùy ý thì có lẽ bạn không muốn -g. Nếu bạn thực sự cần so sánh ký hiệu khoa học -g, thì bạn có thể muốn trích xuất dữ liệu bảng chữ cái và số và thực hiện so sánh riêng biệt .

Nếu bạn chỉ cần 1, -1phân loại số thông thường (ví dụ ) và cảm thấy điều đó 0x/E/+ sortingkhông quan trọng, chỉ cần sử dụng -nđủ:

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=en_US.UTF-8 sort -n myfile
-1000
-22
-13
-11
-010
-10
-5
-2
-1
-0.2
-0.12
-0.11
-0.1
0x1
0x11
0xb
+1
+11
+2
-a
-aa
--aa
-aaa
-b
baa
BAA
bbb
+ignore
inf
-inf
--inf
--inf  
--inf- 
--inf--
-inf--
--inf-a
   naN
Nana
nani lol
--nnf
nnf--
   nnn  
None         
uum
Zero cool
-zzz
1
1.1
1.234E10
5
11

Một trong hai -ghoặc -n, lưu ý về hiệu ứng ngôn ngữ . Bạn có thể muốn chỉ định LC_NUMERICus_EN.UTF-8 để tránh sắp xếp fr_FR.UTF-8 -với số thực không thành công :

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=fr_FR.UTF-8 sort -n myfile
-10
-5
-2
-1
-1.1
-1.2
-0.1
-0.11
-0.12
-0.2
-a
+b
middle
-wwe
+zoo
1
1.1

Với LC_NUMERIC=en_US.UTF-8:

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=en_US.UTF-8 sort -n myfile
-10
-5
-2
-1.2
-1.1
-1
-0.2
-0.12
-0.11
-0.1
-a
+b
middle
-wwe
+zoo
1
1.1

Hoặc LC_NUMERIC=us_EN.UTF-8nhóm +|-|spacevới alpha:

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=us_EN.UTF-8 sort -n myfile
-0.1
    a
    b
 a
 b
+b
+zoo
-a
-wwe
middle
1

Bạn có thể muốn chỉ định localekhi sử dụng sortnếu muốn viết tập lệnh di động.

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.