จัดเรียงไม่เรียงลำดับบรรทัดด้วยไพพ์ '|' ในนั้นอย่างถูกต้อง


17

ฉันพยายามเรียงลำดับข้อมูลแบบง่าย ๆ อย่างไรก็ตามการเรียงลำดับนั้นไม่ได้เรียงจริง มันย้ายแถวส่วนหัวของฉันไปที่ด้านล่าง แต่สองแถวของฉันที่เริ่มต้นด้วย 241 ถูกแบ่งโดยแถวที่เริ่มต้นด้วย 24

cat sort_fail.csv
column_a|column_b|column_c
241|212|20810378
24|121|2810172
241|213|20810376

sort sort_fail.csv
241|212|20810378
24|121|2810172
241|213|20810376
column_a|column_b|column_c

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

ในกรณีนี้ฉันทำงานด้วย

sort sort_fail.csv --field-separator='|' -k1,1

แต่ฉันรู้สึกว่าไม่จำเป็น ทำไมการเรียงลำดับจึงไม่เรียงลำดับ


2
LC_COLLATE=C sortใช้ ขึ้นอยู่กับสิ่งที่คุณคาดหวังคุณอาจต้องใช้LC_COLLATE=C sort -t'|' -n
mosvy

3
ในการจัดเรียงข้อมูล "สไตล์ csv" คุณอาจต้องการใช้csvsortจากcsvkitซึ่งจัดการค่าที่ยกมาอย่างเหมาะสม
Bakuriu

คำตอบ:


32

sort เป็นสถานที่ที่ทราบดังนั้นขึ้นอยู่กับการตั้งค่า LC_COLLATE ของคุณ (ซึ่งสืบทอดมาจาก LANG) คุณอาจได้รับผลลัพธ์ที่แตกต่างกัน:

$ LANG=C sort sort_fail.csv 
241|212|20810378
241|213|20810376
24|121|2810172
column_a|column_b|column_c

$ LANG=en_US sort sort_fail.csv
241|212|20810378
24|121|2810172
241|213|20810376
column_a|column_b|column_c

สิ่งนี้อาจทำให้เกิดปัญหาในสคริปต์เนื่องจากคุณอาจไม่ทราบว่ามีการตั้งค่าการโทรเป็นอะไรและอาจได้รับผลลัพธ์ที่แตกต่างกัน

ไม่ใช่เรื่องแปลกที่สคริปต์จะบังคับให้มีการตั้งค่าที่จำเป็น

เช่น

$ grep 'LC.*sort' /bin/precat
      LC_COLLATE=C sort -u | prezip-bin -z "$cmd: $2"

ตอนนี้สิ่งที่น่าสนใจที่นี่คือ|ตัวละครดูแปลก ๆ

แต่นั่นเป็นเพราะกฎเริ่มต้นสำหรับ en_US ซึ่งได้มาจาก ISO กล่าว

$ grep 007C /usr/share/i18n/locales/iso14651_t1_common
<U007C> IGNORE;IGNORE;IGNORE;<j> # 142 |

ซึ่งหมายความว่า|ตัวละครจะถูกละเว้นและลำดับการจัดเรียงจะเป็นถ้าตัวละครไม่มีอยู่ ..

$ tr -d '|' < sort_fail.csv | LANG=C sort
24121220810378
241212810172
24121320810376
column_acolumn_bcolumn_c

และตรงกับการเรียงลำดับ "ที่ไม่คาดคิด" ที่คุณเห็น

การหลีกเลี่ยงปัญหาคือการใช้-n(เพื่อบังคับให้เรียงลำดับตัวเลข) หรือใช้ตัวคั่นฟิลด์ (เช่นที่คุณทำ) หรือเพื่อใช้Cโลแคล


มโนหร ฉันเห็นความนิยมอื่น ๆ เกี่ยวกับการโลคัลไลซ์เซชัน แต่คิดว่าจะส่งผลกระทบต่อการเรียงลำดับสัมพัทธ์ของ 24 vs 241 ไม่ใช่อย่างนี้
user10777668

7
สิ่งที่มีประโยชน์เป็นพิเศษในการจัดเรียง GNU คือ--debugตัวเลือกซึ่งระบุคีย์ (ขีดเส้นใต้) ที่ใช้ในการเปรียบเทียบ
Jeff Schaller

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

นั่นเป็นเหตุผลที่ฉันพูดถึงมัน @ user10777668 - มันบ่งบอกว่าsortกำลังใช้ทั้งบรรทัดแทนที่จะหยุดที่ตัวละครที่เราคิดเอาไว้
Jeff Schaller

ฉันไม่ได้คาดหวังให้มันหยุด ฉันคาดหวังว่ามันจะรับรู้ถึงตัวละครไปป์และรวมไว้ในการเรียงลำดับดังนั้นจึงรักษา 24 | 1 และ 241 แตกต่างกัน ฉันไม่แน่ใจว่า - debug จะเปลี่ยนแปลงสิ่งนั้นได้อย่างไรและในความเป็นจริงเนื่องจากมันขีดเส้นใต้ | ดูเหมือนว่ามันจะเบี่ยงเบนความสนใจจากปัญหาจริงที่การแปลเป็นภาษาท้องถิ่นนำไปสู่การสวมบทบาทไปป์
user10777668

1

สิ่งระคายเคืองฉันคือการที่ไม่ได้ย้ายจากสถานที่ระหว่างคนทั้งสอง24 ฟิลด์ที่สองเริ่มต้นด้วย241 1ลองเรียงลำดับด้วยลีดเดอร์4ในฟิลด์ที่สอง, ค่า24จะถูกย้ายลงดังนั้นฉันสงสัยว่าsortจะไม่สนใจ|เว้นแต่จะบอกเป็นอย่างอื่น ลองsort -n...


1

-n, - ตัวเลขเรียงลำดับเปรียบเทียบตามค่าตัวเลขสตริง

210
23

หากไม่มี -n, 210 ต่อข้อความจะอยู่ข้างหน้า 23 ขณะที่ไปอักขระตัวละครของฉัน


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