การเรียงหลายคีย์ด้วย Unix sort


137

ฉันมีไฟล์ขนาดใหญ่ที่อาจต้องเรียงลำดับด้วย 1-n keys ปุ่มเหล่านี้บางปุ่มอาจเป็นตัวเลขและบางปุ่มอาจไม่เป็นเช่นนั้น นี่เป็นไฟล์คอลัมน์ความกว้างคงที่ดังนั้นจึงไม่มีตัวคั่น

มีวิธีที่ดีในการทำเช่นนี้กับ Unix เรียง? ด้วยปุ่มเดียวมันง่ายเหมือนการใช้ '-n' ฉันได้อ่านหน้าคนและค้นหา Google อย่างย่อ ๆ แต่ไม่พบตัวอย่างที่ดี ฉันจะทำสิ่งนี้ให้สำเร็จได้อย่างไร

หมายเหตุ: ฉันได้ตัดออก Perl เนื่องจากศักยภาพของขนาดไฟล์ มันจะเป็นทางเลือกสุดท้าย


ข้อมูลตัวอย่างหนึ่งหรือสองบรรทัดจะเป็นประโยชน์สำหรับการสร้างบรรทัดคำสั่งตัวอย่าง นอกจากนี้ปุ่ม "1-n" หมายความว่าคุณจำเป็นต้องเรียงลำดับตามจำนวนของตัวแปรหรือไม่ การทำเช่นนั้นโดยไม่ใช้สคริปต์จะเป็นเรื่องสนุก ...
Ken Gentle

ฉันมีตัวห่อหุ้ม PHP รอบคำสั่ง sort เพื่อเปิดใช้งานคุณสมบัติ 1-n
Chris Kloberdanz

คำตอบ:


69

ใช้-kตัวเลือก (หรือ--key=POS1[,POS2]) มันสามารถปรากฏได้หลายครั้งและแต่ละปุ่มสามารถมีตัวเลือกทั่วโลก (เช่นnการเรียงลำดับตัวเลข)


7
จากหน้าตัวเรียงลำดับ: "POS คือ F [.C] [OPTS] โดยที่ F คือหมายเลขฟิลด์และ C ตำแหน่งอักขระในฟิลด์ซึ่งทั้งคู่เป็นจุดเริ่มต้น 1" ดู man page สำหรับเอกสารฉบับเต็ม
Adam Rosenfield

49
ดูคำตอบของ andras ด้วยหากคุณไม่ต้องการเสียสติ
รอน

1
ความคิดเห็นทั้งสองด้านบนนั้นถูกต้องและเพิ่มเติม ขอบคุณสุภาพบุรุษ
Ken Gentle

314

ดูแลว่า:

หากคุณต้องการเรียงลำดับไฟล์ตามฟิลด์ 3 เป็นหลักและอันดับที่สองตามฟิลด์ 2 คุณต้องการสิ่งนี้:

sort -k 3,3 -k 2,2 < inputfile

ไม่ใช่สิ่งนี้: sort -k 3 -k 2 < inputfileซึ่งเรียงลำดับไฟล์ตามสตริงจากจุดเริ่มต้นของฟิลด์ 3 ถึงจุดสิ้นสุดบรรทัด (ซึ่งอาจไม่ซ้ำกัน)

-k, --key=POS1[,POS2]     start a key at POS1 (origin 1), end it at POS2
                          (default end of line)

8
การเปลี่ยนแปลงชีวิต ขอบคุณ
davidtbernal

2
อ๊ะ! ตอนนี้ฉันต้องแก้ไขสคริปต์เพราะก่อนหน้านี้ฉันเห็นคำตอบแรกข้างต้นเท่านั้น ... สิ่งที่ดีฉันยังไม่ได้พึ่งสคริปต์เอาต์พุตเลย ....
Wildcard

ดี! ทีนี้จะเกิดอะไรขึ้นถ้าฉันต้องการให้ fleld 3 เป็นตัวเลขและเรียงกลับกันในขณะที่ฟิลด์ 2 จะเรียงลำดับที่ไม่ใช่ตัวเลขและปกติ :)
อรุณ

2
@Arun POS ได้อธิบายไว้ที่ส่วนท้ายของหน้าคน คุณเพียงแค่เพิ่มตัวเลือกการสั่งซื้อไปยังหมายเลขฟิลด์เช่นนี้:sort -k 3,3nr -k 2,2
andras

1
aargh อะไรคืออินเทอร์เฟซที่ใช้งานง่าย-k2ควรเป็น-k2,2และเครื่องหมายจุลภาคต่อท้าย-k2,ควรเป็น 'จุดเริ่มต้นของการสิ้นสุดบรรทัดหรืออะไรก็ตาม'
android.weasel

94

ตัวเลือก -k คือสิ่งที่คุณต้องการ

-k 1.4,1.5n -k 1.14,1.15n

จะใช้ตำแหน่งอักขระ 4-5 ในฟิลด์แรก (เป็นฟิลด์เดียวทั้งหมดสำหรับความกว้างคงที่) และเรียงลำดับตัวเลขเป็นคีย์แรก

คีย์ที่สองจะเป็นอักขระ 14-15 ในฟิลด์แรกเช่นกัน

(แก้ไข)

ตัวอย่าง (ทั้งหมดที่ฉันมีคือ DOS / cygwin สะดวก):

dir | \cygwin\bin\sort.exe -k 1.4,1.5n -k 1.40,1.60r

สำหรับข้อมูล:

12/10/2008  01:10 PM         1,564,990 outfile.txt

เรียงลำดับรายชื่อไดเรกทอรีตามหมายเลขเดือน (pos 4-5) ตัวเลขแล้วตามด้วยชื่อไฟล์ (pos 40-60) ในทางกลับกัน เนื่องจากไม่มีแท็บจึงเป็นฟิลด์ 1 สำหรับเรียงลำดับ


มันเป็นเพียงหนึ่งช่องถ้าไม่มีช่องว่างในข้อมูลอินพุต อย่างไรก็ตามตัวอย่างของคุณมีประโยชน์
Jonathan Leffler

การแก้ไข: หากไม่มี / แท็บ / ในข้อมูลอินพุต ในเอาต์พุตคำสั่ง 'dir' ของ DOS ไม่มีแท็บ
Clinton Pierce

ตัวอย่างเกี่ยวกับวิธีใช้ตัวเลือก (ตัวเลข, ย้อนกลับ) มีประโยชน์อย่างยิ่งเนื่องจากแทบจะเป็นไปไม่ได้ที่จะหาวิธีใช้เพียงแค่จากหน้าคนและคำตอบอื่น ๆ ไม่ได้กล่าวถึง ฉันหวังว่าฉันจะได้ +2 สำหรับสิ่งนี้ ;)
msb

22

นี่คือการเรียงลำดับคอลัมน์ต่างๆในไฟล์ csv ตามลำดับตัวเลขและพจนานุกรมคอลัมน์ 5 และหลังเป็นลำดับพจนานุกรม

~/test>sort -t, -k1,1n -k2,2n -k3,3d -k4,4n -k5d  sort.csv
1,10,b,22,Ga
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C

~/test>cat sort.csv
2,3,a,9,C
2,2,b,20,F
2,2,c,19,Gb,hj
2,2,c,19,Gb,hi
2,2,c,19,Ga
2,2,b,22,Ga
1,10,b,22,Ga

สังเกตว่า -k1,1n หมายถึงตัวเลขเริ่มต้นที่คอลัมน์ 1 และสิ้นสุดที่คอลัมน์ 1 ถ้าฉันทำด้านล่างมันจะมีการต่อคอลัมน์ 1 และ 2 เข้าด้วยกันทำให้มี 1,10 เรียงเป็น 110

~/test>sort -t, -k1,2n -k3,3 -k4,4n -k5d  sort.csv
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C
1,10,b,22,Ga

1
นี่เป็นคำตอบที่ดีที่สุดเพราะมันแสดงให้เห็นถึงวิธีการใช้สวิตช์ที่แตกต่างกันสำหรับคอลัมน์ที่แตกต่างกัน
xaxa

12

ฉันเชื่อในกรณีของคุณบางอย่างเช่น

sort -t@ -k1.1,1.4 -k1.5,1.7 ... <inputfile

จะทำงานได้ดีขึ้น @ คือตัวคั่นฟิลด์ตรวจสอบให้แน่ใจว่าเป็นอักขระที่ไม่ปรากฏ ดังนั้นข้อมูลที่คุณป้อนเข้ามานั้นจะประกอบด้วยหนึ่งคอลัมน์

แก้ไข: เห็นได้ชัดว่า clintp ได้ให้คำตอบที่คล้ายกันแล้วขอโทษ ในขณะที่เขาชี้ให้เห็นธง 'n' และ 'r' สามารถเพิ่มลงในตัวเลือก -k ....


แม้ว่าตัวคั่นเริ่มต้นที่สอดคล้องกับเอกสารgnu.org/software/coreutils/manual/html_node/…เป็นช่องว่างบางครั้งการนับฟิลด์ไม่ใช่สิ่งที่คุณคาดหวัง บางทีอย่างที่คนอื่น ๆ พูดที่นี่เพราะการตั้งค่าโลแคล LC_CTYPE เมื่อสงสัยนับจากจุดเริ่มต้นของบรรทัด!
แบรดเดร

5

โปรดทราบว่าอาจต้องการปรับเสถียรภาพการเรียงด้วย-sสวิตช์เพื่อให้บรรทัดที่มีอันดับเท่ากันรักษาลำดับเดิมของตนในเอาต์พุตด้วย


2

ฉันแค่ต้องการเพิ่มเคล็ดลับเมื่อคุณใช้การเรียงลำดับระมัดระวังเกี่ยวกับสถานที่ของคุณที่มีผลต่อลำดับการเปรียบเทียบคีย์ ฉันมักจะใช้ LC_ALL = C อย่างชัดเจนเพื่อสร้างสถานที่ที่ฉันต้องการ


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