อะไรคือความแตกต่างระหว่าง - ตัวเลือก - ตัวเลข - เรียงลำดับทั่วไปและ - ตัวเลข - เรียงลำดับในการเรียงลำดับ gnu


113

sortจัดเรียงตัวเลขสองประเภท นี่มาจากหน้าคน:

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

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

อะไรคือความแตกต่าง?


17
โปรดทราบว่าเอกสารฉบับเต็มsortไม่ใช่manหน้า แต่เป็นinfoหน้า ( info sort)
a3nm

คำตอบ:


85

การเรียงลำดับตัวเลขทั่วไปจะเปรียบเทียบตัวเลขเป็นตัวเลขซึ่งช่วยให้สัญกรณ์ทางวิทยาศาสตร์เช่น 1.234E10 แต่ช้ากว่าและอาจมีข้อผิดพลาดในการปัดเศษ (1.2345678 อาจมาหลัง 1.2345679) การเรียงลำดับตัวเลขเป็นเพียงการเรียงตัวอักษรปกติที่รู้ว่า 10 มาหลัง 9

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

'-g' '--general-numeric-sort' '--sort = general-numeric' เรียงลำดับตัวเลขโดยใช้ฟังก์ชัน C มาตรฐานเพื่อแปลงคำนำหน้าของแต่ละบรรทัดให้เป็นเลขทศนิยมที่มีความแม่นยำสองเท่า ซึ่งทำให้สามารถระบุตัวเลขทศนิยมในสัญกรณ์วิทยาศาสตร์เช่น 1.0e-34 และ 10e100 โลแคล LC_NUMERIC กำหนดอักขระจุดทศนิยม อย่ารายงานข้อผิดพลาดล้นขาดหรือเกิด Conversion ใช้ลำดับการเรียงต่อไปนี้: เส้นที่ไม่ได้ขึ้นต้นด้วยตัวเลข (ทั้งหมดถือว่าเท่ากัน) NaN (ค่า“ ไม่ใช่ตัวเลข” ในเลขคณิตทศนิยมของ IEEE) ในลำดับที่สอดคล้องกัน แต่ขึ้นอยู่กับเครื่อง ลบอินฟินิตี้ ตัวเลข จำกัด ตามลำดับตัวเลขจากน้อยไปมาก (โดยมี -0 และ +0 เท่ากัน) บวกอินฟินิตี้

ใช้ตัวเลือกนี้เฉพาะในกรณีที่ไม่มีทางเลือกอื่น ช้ากว่า --numeric-sort (-n) มากและอาจสูญเสียข้อมูลเมื่อแปลงเป็นทศนิยม

'-n' '--numeric-sort' '--sort = numeric' เรียงลำดับตัวเลข ตัวเลขเริ่มต้นแต่ละบรรทัดและประกอบด้วยช่องว่างที่เป็นทางเลือกเครื่องหมาย '-' ที่เป็นทางเลือกและตัวเลขที่เป็นศูนย์หรือมากกว่าซึ่งอาจคั่นด้วยตัวคั่นหลายพันตัวเลือกตามด้วยอักขระจุดทศนิยมและตัวเลขศูนย์หรือมากกว่า ตัวเลขว่างจะถือว่าเป็น "0" โลแคล LC_NUMERIC ระบุอักขระจุดทศนิยมและตัวคั่นหลักพัน ตามค่าเริ่มต้นช่องว่างคือช่องว่างหรือแท็บ แต่โลแคล LC_CTYPE สามารถเปลี่ยนแปลงสิ่งนี้ได้

การเปรียบเทียบเป็นสิ่งที่แน่นอน ไม่มีข้อผิดพลาดในการปัดเศษ

ไม่รู้จักทั้งเครื่องหมาย '+' นำหน้าหรือเลขชี้กำลัง หากต้องการเปรียบเทียบสตริงดังกล่าวในเชิงตัวเลขให้ใช้ตัวเลือก --general-numeric-sort (-g)


2
ขอบคุณ. แปลกที่หน้าผู้ชายและข้อมูลไม่มีสิ่งนี้อยู่ในนั้น ฉันยังไม่ทราบเกี่ยวกับgnu.org/software/coreutils/manual/html_node/index.html
เทรนตัน

6
สิ่งนี้ไม่ได้ผลสำหรับฉัน ฉันกำลังจัดเรียงไฟล์ด้วยคอลัมน์ที่สามที่มีเนื้อหาเช่น R1 R2 R10 R15 ใช้อย่างใดอย่างหนึ่ง-k3.2nหรือ-k3.2gเป็นการเรียงลำดับR10ก่อนหน้าR2นี้ การจัดเรียงเป็นศัพท์ไม่ใช่ตัวเลข ฉันคาดหวังว่ามันจะถือว่าฟิลด์ตั้งแต่อักขระตัวที่สองเป็นต้นไปเป็นตัวเลข
Kaz

6
@Kaz: ข้อมูลsortจำเพาะที่สำคัญ เป็นไบแซนไทน์อย่างแท้จริง - สั้น ๆ คือ: ช่องว่างที่อยู่ข้างหน้าฟิลด์ถือเป็นส่วนหนึ่งของฟิลด์ดังนั้นถ่าน ดัชนี 1 ชี้ไปยังช่องว่าง (แรก) ที่อยู่ข้างหน้าฟิลด์ไม่ใช่อักขระตัวแรกที่แท้จริงของฟิลด์ ต่อท้ายตัวอักษร ดัชนีด้วยbเพื่อแก้ไขปัญหานี้เช่น: -k 3.2bn,3(โปรดทราบว่าตัวเลือกส่วนกลาง ไม่ทำงานในกรณีนี้) นอกจากนี้ยังทราบเพิ่มซึ่งทำให้มั่นใจได้ว่ามีเพียงสนามที่ 3 จะใช้ - ไม่ดัชนีฟิลด์ที่ 2 ที่เหลือของสายทั้งหมดถูกนำมาใช้ -b,3
mklement0

11

คุณควรระมัดระวังกับสถานที่ของคุณ ตัวอย่างเช่นคุณอาจต้องการจัดเรียงตัวเลขลอยตัว (เช่น 2.2) ในขณะที่ภาษาของคุณอาจคาดหวังให้ใช้เครื่องหมายจุลภาค (เช่น 2,2)

ตามที่รายงานในฟอรัมนี้คุณอาจพบผลลัพธ์ที่ไม่ถูกต้องโดยใช้แฟล็ก -n หรือ -g

ในกรณีของฉันฉันใช้:

LC_ALL=C sort -k 6,6n file

เพื่อจัดเรียงคอลัมน์ที่ 6 ที่มี:

2.5
3.7
1.4

เพื่อให้ได้

1.4
2.5
3.7

2
แม้จะใช้ LANG = C ฉันไม่สามารถ-nจำเครื่องหมายจุลภาคเป็นตัวคั่นหลักพันได้ -“ 1,000” จะถือว่าเหมือนกับ“ 1”
Scott

1
นั่นควรจะเป็น LC_ALL = C
Stuart P. Bentley

@Scott: อันที่จริงไม่รู้จักตัวคั่นหลายพันตัว: sortใช้ตรรกะคำนำหน้าที่ยาวที่สุด: ส่วนที่ยาวที่สุดของบรรทัด / คีย์ที่รับรู้ว่าใช้ตัวเลข ในสถานที่ที่ใช้เป็นตัวละครกี่ก็จะหยุดอ่านที่. ,
mklement0

@ StuartP Bentley: LC_ALL=Cเป็นตัวเลือกที่แข็งแกร่งที่สุด อย่างไรก็ตามหากLC_ALLไม่ได้เดิมพันชุดLANG=Cก็จะได้ผลเช่นกัน
mklement0

1
จุดดี แต่LANG=C sort -k 6,6n fileทั้งง่ายกว่าและยังแปลผลของการตั้งค่าตัวแปรสภาพแวดล้อมLANGให้เป็นคำสั่งเฉพาะ
mklement0

0

นอกเหนือจากคำตอบที่ยอมรับซึ่งกล่าวถึง-gอนุญาตให้ใช้สัญกรณ์ทางวิทยาศาสตร์แล้วฉันต้องการแสดงให้เห็นถึงส่วนที่น่าจะเป็นสาเหตุของพฤติกรรมที่ไม่พึงปรารถนา

ด้วย-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

ดูzooสามสิ่งสำคัญที่นี่:

  • บรรทัดเริ่มต้นด้วยNAN(เช่นNanaและnani lol) หรือ-INF(ขีดเดียวไม่ใช่--INF) เลื่อนไปที่จุดสิ้นสุด แต่ก่อนหลัก ในขณะที่INFการย้ายไปที่ผ่านมาหลังจากที่ตัวเลขเพราะมันหมายถึงอินฟินิตี้

  • NAN, INFและ-INFเป็นกรณีตาย

  • สายเสมอละเว้นช่องว่างจากด้านข้างของทั้งNAN, INF, -INF (ไม่LC_CTYPE) ตัวอักษรอื่น ๆ อาจละเว้นช่องว่างจากด้านใดด้านหนึ่งขึ้นอยู่กับโลแคลLC_COLLATE(เช่นLC_COLLATE=fr_FR.UTF-8ละเว้น แต่LC_COLLATE=us_EN.UTF-8ไม่เพิกเฉย)

ดังนั้นหากคุณกำลังเรียงลำดับตัวอักษรและตัวเลขพล-gแล้วคุณอาจไม่ต้องการ หากคุณต้องการเปรียบเทียบค่าทางวิทยาศาสตร์จริงๆ-gแล้วคุณอาจต้องการที่จะดึงตัวอักษรและข้อมูลที่เป็นตัวเลขและทำเปรียบเทียบแยกต่างหาก

หากคุณต้องการเพียงตัวเลขธรรมดา (เช่น1, -1) การเรียงลำดับและรู้สึกว่า0x/E/+ sortingไม่สำคัญให้ใช้ให้-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

อย่างใดอย่างหนึ่ง-gหรือ-nให้ตระหนักถึงผลกระทบที่เกิดเหตุ คุณอาจต้องการที่จะระบุLC_NUMERICเป็นus_EN.UTF-8 เพื่อหลีกเลี่ยงการ fr_FR.UTF-8 เรียง-ลอยตัวจำนวนล้มเหลว :

$ 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

ด้วย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

หรือLC_NUMERIC=us_EN.UTF-8จะจัดกลุ่ม+|-|spaceกับ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

คุณอาจต้องการระบุlocaleเมื่อใช้sortถ้าต้องการเขียนสคริปต์แบบพกพา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.