วิธี UNIX จัดเรียงตามหนึ่งคอลัมน์เท่านั้นได้อย่างไร


47

ฉันรู้ว่าตัวเลือก -k สำหรับ Unix เรียงลำดับช่วยให้เราสามารถจัดเรียงตามคอลัมน์ที่เฉพาะเจาะจงและต่อไปนี้ทั้งหมด ตัวอย่างเช่นกำหนดไฟล์อินพุต:

2 3
2 2
1 2
2 1
1 1

ใช้sort -n -k 1ฉันได้รับผลลัพธ์เรียงตามคอลัมน์ที่ 1 แล้วตามด้วยที่ 2:

1 1
1 2
2 1
2 2
2 3

อย่างไรก็ตามฉันต้องการคงคอลัมน์ที่ 2 ไว้อย่างนี้:

1 2
1 1
2 3
2 2
2 1

เป็นไปได้ด้วยsortคำสั่งหรือไม่

คำตอบ:


64

ลองดูสิ:

sort -s -n -k 1,1

การ-sเรียงลำดับ 'สุดท้าย' ปิดใช้งานซึ่งเรียงลำดับทุกสิ่งที่ไม่ได้เป็นส่วนหนึ่งของคีย์ที่ระบุ

-k 1ไม่จริงหมายถึง "ด้านนี้และต่อไปนี้ทั้งหมด" ในบริบทของการจัดเรียงตัวเลขตามที่คุณสามารถดูได้ว่าคุณพยายามที่จะเรียงลำดับในคอลัมน์ที่สอง คุณแค่เห็นความสัมพันธ์ที่ขาดไปโดยไปที่สายที่เหลือ โดยทั่วไป แต่คุณจะต้องระบุ-k 1,1ในการจัดเรียงเฉพาะบนสนามหนึ่ง


คุณพูดถูก นี่คือสิ่งที่ฉันต้องการ ขอบคุณ!

เป็นไปได้หรือไม่ที่จะใช้การเข้าร่วมกับผลลัพธ์ของการเรียงลำดับนี้
MiNdFrEaK

@MiNdFrEaK: ความต้องการjoinคืออินพุตถูกเรียงลำดับในฟิลด์ที่คุณเข้าร่วม แน่นอนว่าผลลัพธ์นี้ถูกจัดเรียงในฟิลด์แรกและคุณสามารถเข้าร่วมได้
Cascabel

ฉันมี 2 ไฟล์หนึ่งมี 2 คอลัมน์อีกหนึ่งมี 1 คอลัมน์ ไฟล์ที่สองถูกเรียงลำดับโดยใช้ sort -u ตอนนี้งานคือฉันต้องเข้าร่วมคอลัมน์นี้กับคอลัมน์แรกของไฟล์แรกซึ่งไม่ได้จัดเรียงดังนั้นสิ่งที่จะเป็นไวยากรณ์หรือไม่ จะใช้งานได้ไหม เข้าร่วม -j 1 file2.txt sort -s -n -k 1 file1.txt หรือไม่
MiNdFrEaK

1
ส่วน-k 1,1(" 1 ") ไม่ได้ผลดีกว่าสำหรับฉัน สิ่งที่ทำงานเป็น-s -k 1ด้วย-nถ้าคุณต้องการมัน
Totor

10

หากต้องการเรียงลำดับเฉพาะในคอลัมน์แรกคุณควรทำ:

sort -n -s -k1,1

จากคู่มือการบริหารระบบ Unix และ Linux

sort ยอมรับคีย์ข้อมูลจำเพาะ -k3 (แทนที่จะเป็น -k3,3) แต่อาจไม่ทำในสิ่งที่คุณคาดหวัง หากไม่มีหมายเลขฟิลด์ยกเลิกคีย์การเรียงลำดับจะยังคงอยู่ที่จุดสิ้นสุดของบรรทัด


ไม่ทำงานสำหรับฉันฉันต้องเพิ่ม-sตัวเลือกเนื่องจาก Cascabel ชี้ให้เห็น
Jean Paul

@JeanPaul คุณถูกต้องเอกสารประกอบสำหรับการ-sพูดว่า "ตัวเลือกนี้จะรักษาลำดับการบันทึกดั้งเดิมของระเบียนที่มีคีย์เท่ากับ"
tidbeck

2

โดยทั่วไปแล้วคำตอบที่ให้มาไม่มีสำหรับฉัน

ทั้งสองsort -s -k 2 file1และsort -n -k1,1ทำการเรียงลำดับเพิ่มเติมด้วยไฟล์นี้:

# cat file1
 3 3 5
 3 2 3
 1 4 7
 0 1 2
 3 2 1

ฉันแค่ต้องทำสิ่งนี้และลงเอยด้วยการใช้เชลล์ลูป วิธีการแก้ปัญหานี้อาจทำงานได้ไม่ดีกับไฟล์ที่มีขนาดใหญ่มากเพราะต้องอ่านทั้งไฟล์สำหรับแต่ละค่าที่ไม่ซ้ำกันในคอลัมน์ที่เรียงลำดับ

ที่นี่ไฟล์จะถูกจัดเรียงในคอลัมน์ 2 เท่านั้น

# awk '{print $2}' file1 | sort | uniq | while read index
do  
    awk -v var=$index '$2 == var { print $0}' file1 
done
 0 1 2
 3 2 3
 3 2 1
 3 3 5
 1 4 7

sort -s -k2,2 file1
plhn

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