วิธีการเรียงลำดับแบบกำหนดเองโดยใช้การเรียงลำดับยูนิกซ์?


11

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

ไฟล์ตัวอย่างก่อนการเรียงลำดับใด ๆ :

C,United States,WA,Tacoma,f,1
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2
A,United States,NY,New York,f,1

จัดเรียงไฟล์: $ sort -t ',' -k 2,2 -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

ผลการจัดเรียง:

A,Bahamas,Bahamas,Nassau,f,2
A,Canada,QC,Montreal,f,2
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1

นี่คือปัญหา: ฉันต้องการจัดเรียงคอลัมน์ 2 ตามการเรียงลำดับที่กำหนดเองซึ่งหมายถึงฉันต้องการให้สหรัฐอเมริกาก่อนจากนั้นก็แคนาดาและบาฮามาส:

การจัดเรียงที่ต้องการ:

A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2

มีวิธีการเรียงลำดับยูนิกซ์เรียงลำดับแบบกำหนดเองที่สามารถใช้? สิ่งที่ต้องการ: $ sort -t ',' -k 2,2:'United States, Canada, Bahamas' -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

ขอบคุณ!


3
สำหรับค่าทั้งสามนี้คุณต้องการเรียงลำดับตามตัวอักษรย้อนกลับ สำหรับกรณีทั่วไปคุณจะต้องแมปชื่อกับหมายเลขลำดับการเรียงแล้วทำการเรียงลำดับโดยใช้หมายเลขลำดับการเรียง หรือใช้ภาษาสคริปต์ ... ความเป็นไปได้อย่างหนึ่งคือjoinคำสั่ง แต่คุณสามารถเรียงลำดับได้มากมาย - ไฟล์อินพุตสำหรับjoinจะต้องเรียงลำดับเดียวและคุณจะใช้sortอีกครั้งเพื่อใส่ข้อมูลลงใน คำสั่งซื้ออื่น (และการสูญเสียคอลัมน์เรียงลำดับเป็นขั้นตอนหลังการเรียงลำดับ)
Jonathan Leffler

ในอินพุตตัวอย่างของคุณไม่ควรมีtแทนที่จะเป็นfในบรรทัดสุดท้ายหรือไม่
Lev Levitsky

เลวี: ใช่จับได้ดี ความผิดฉันเอง; การตัดและวางมากเกินไป (ชุดข้อมูลจริงของฉันมีขนาดใหญ่กว่ามากและฉันบังเอิญจับแถวผิด)

ฉันอัปเดตคำตอบเพื่อให้ตรงกับข้อมูลของคุณ
Lev Levitsky

คำตอบ:


8

คำตอบและความคิดเห็นอื่น ๆ ตอบคำถามโดยทั่วไปนี่คือลักษณะการใช้งานที่มีลักษณะ:

$ cat order
Bahamas,3
Canada,2
United States,1

$ cat data
C,United States,WA,Tacoma,f,1
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2
A,United States,NY,New York,f,1

$ sort -t, -k2 data | join -t, -11 -22 order - | sort -t, -k2n -k4,5 -k6r -k7nr | cut -d, -f 3,1,4-7
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2

เยี่ยมมากขอบคุณสำหรับความช่วยเหลือของคุณ มันทำงานได้อย่างสมบูรณ์แบบ!

@jewelia ปรับปรุงอีกครั้งsedไม่จำเป็นต้องใช้ที่นี่จริงๆ
Lev Levitsky

1

คุณไม่สามารถทำเช่นนั้นได้มีการจัดเรียง ณ จุดนี้คุณควรจะได้รับการเข้าถึงสำหรับawk / Perl / ภาษาของคุณของตัวเลือก คุณสามารถทำให้เหลวไหลได้ ตัวอย่างเช่นคุณสามารถใช้ sed เพื่อเปลี่ยน "United States" เป็น 0, "Canada" เป็น 1 และ "Bahamas" เป็น 2 จากนั้นทำการเรียงลำดับตัวเลขกับคอลัมน์นั้นจากนั้นกดกลับ หรือเปลี่ยน "United States" เป็น "United States, 0" ฯลฯ เรียงจากคอลัมน์พิเศษแล้วละทิ้ง


0

ฉันเพิ่งเขียนผู้ช่วยที่เรียกว่า csortเพื่อให้ง่ายต่อการทำสิ่งนี้ มันนำหน้าแต่ละบรรทัดด้วยค่าที่คุณเลือกโดยยึดตามซับสตริงหรือนิพจน์ทั่วไปที่ตรงกันภายในบรรทัด:

$ csort -t, '2=United States' X 2=Canada Y 2=Bahamas Z < tmp.csv | \
sort -t, -k1,1 -k3,3 -k4,4 -k5,5 -k6,6r -k7,7nr
X,A,United States,MA,Boston,f,0
X,B,United States,NY,New York,f,5
X,A,United States,NY,New York,f,1
X,C,United States,WA,Tacoma,f,1
Y,A,Canada,QC,Montreal,f,2
Z,A,Bahamas,Bahamas,Nassau,f,2

2=STRสัญกรณ์หมายถึง "การแข่งขันถ้าฟิลด์ที่สองเท่ากับSTR"

จากนั้นคุณสามารถเลือกไพพ์เอาต์พุตผ่านcut -c3-เพื่อลบคำนำหน้า

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